在 rails 中的相同表单中创建 has_and_belongs_to_many 个对象

Creating has_and_belongs_to_many objects within the same form in rails

我正在构建一个 rails 应用程序,使用 devise 进行身份验证,使用 cancan 进行授权。我有一个表格,您可以在其中创建一个 "post",每个 post has_and_belongs_to 许多 "tags"。

我想创建一个系统来创建类似于堆栈溢出的标签,其中标签只需通过单个文本框输入,然后在服务器端转换为适当的标签对象。最初我只是有一个文本框,我可以在其中输入一个字符串,然后该字符串将在控制器中被解析

@post.tags << params[:post][:tags].split(' ').map{ |name| Tag.createOrReturnExisting name}

效果很好..直到我添加了 cancan 授权,这要求我添加

def post_params
  params.require(:post).permit(:title,:description,:tags,:content,:types_id)
end

到我的控制器,这现在导致在尝试创建 Post undefined method each for "Tag1 Tag2 Tag3\r\n":String 时抛出以下错误我假设这是因为它试图将文本框中的字符串处理为在我有机会对其进行格式化之前的一组标签。

所以我的问题是,我必须如何格式化我的控制器、模型或视图才能在它到达 post_params 方法之前解析字符串?

这是我的模型、视图和控制器

标签模型

class Tag < ActiveRecord::Base
    has_and_belongs_to_many :post, join_table: 'tag_posts' 

    def self.createOrReturnExisting title
        if Tag.any? {|tag| tag.title == title} 
            logger.debug "Tag: #{title} already exists"
            Tag.find_by title: title
        else
            logger.debug "Tag: #{title} created"
            Tag.new title: title
        end
    end
end

Post 型号

class Post < ActiveRecord::Base
    belongs_to :user
    has_and_belongs_to_many :tags, join_table: 'tags_posts'
    has_one :type

    validates :title, presence: true, length: { maximum: 50 }
    validates :description, presence: true, length: { maximum: 255 }
    validates :types_id, presence: true, length: { maximum: 255 }
end

new.html.erb

<h1>Post#new</h1>
<p>Find me in app/views/post/new.html.erb</p>

<%= form_for @post do |f| %>

    Title: <%= f.text_field :title %>
    Description: <%= f.text_area :description %>
    Type: <%= f.collection_select( :types_id, Type.all, :id, :title ) %>
    Content: <%= f.text_area :content%>
    Tags: <%= f.text_area :tags%>

    <%= f.submit %>

<% end %>

Post控制器

class PostsController < ApplicationController

    load_and_authorize_resource

    def miniList
        render 'miniList'
    end
  def create
        @post = Post.new
        @post.title = params[:post][:title]
        @post.description = params[:post][:description]
        @post.content = params[:post][:content]
        @tagStrings = params[:post][:tags].split(' ')
        puts @tagStrings

        @tagStrings.map do |name|
          @tags << Tag.createOrReturnExisting name
        end
        @post.tags = @tags
        @post.types_id = params[:post][:types_id]
        if @post.save!
            flash[:success] = "Post Saved Successfully"
        else
            flash[:error] = "Post not saved"
        end
        current_user.posts << @post
        redirect_to :root
  end

  def new

        @post = Post.new
        render 'new'
  end

  def edit 
  end

  def update
  end

  def delete
  end

    private
        def post_params
            params.require(:post).permit(:title,:description,:tags,:content,:types_id)
        end
end

我明白了,我需要做的是将 load_and_authorize_resource 更改为 authorize_resource,因为我不希望 cancan 弄乱我的参数,这只会让它检查我的控制器的授权行动,然后让其余的人独自一人。我仍然希望有一种更直观的方法来做到这一点,但这可以满足我的需要