Rails 3: Multiple Select with has_many through associations

后端 未结 5 2064
温柔的废话
温柔的废话 2020-11-27 11:24

I want to get possibility to select several Categories for one Post with multiple select.

I have next models: Post, Category and PostCategory.

class          


        
相关标签:
5条回答
  • 2020-11-27 11:40

    Sorry to resurrect the dead, but I found a much simpler solution that lets one use the default controller action code and use the ActiveModel setter logic for a has_many. Yes, it's totally magic.

    <%= f.select :category_ids, Category.all.collect {|x| [x.name, x.id]}, {}, :multiple => true %>
    

    Specifically, using the :category_ids (or :your_collection_ids) param name will automagically tell Rails to call @post.category_ids = params[:post][:category_ids] to set the categories for that post accordingly, all without modifying the default controller/scaffold #create and #update code.

    Oh, and it works with has_many :something, through: :something_else automatically managing the join model. Freaking awesome.

    So from the OP, just change the field/param name to :category_ids instead of :categories.

    This will also automatically have the model's selected categories populate the select field as highlighted when on an edit form.

    References:

    From the has_many API docs where I found this.

    Also the warning from the form helpers guide explains this "type mismatch" when not using the proper form-field/parameter name.

    By using the proper form-field/param name, you can dry up new and edit forms and keep the controllers thin, as encouraged by the Rails way.

    note for rails 4 and strong parameters:

    def post_params
      params.require(:post).permit(:title, :body, category_ids: [])
    end
    
    0 讨论(0)
  • 2020-11-27 11:45

    What you need is a list of options for the select:

    <%= f.select :category_id, Category.all.collect {|x| [x.name, x.id]}, :multiple => true %>
    
    0 讨论(0)
  • 2020-11-27 11:45

    Tigraine almost had it, but you need to specify an additional empty hash:

    <%= f.select :category_id, Category.all.collect {|x| [x.name, x.id]}, {}, :multiple => true %>

    0 讨论(0)
  • 2020-11-27 11:50

    As the @post does not have id, the from might not display categories as there is no association. You need to pass do a build on @post something like

     @post = Post.new(:categories => Category.all)
    
    0 讨论(0)
  • 2020-11-27 11:56

    Final solution to organize categories in your posts, I hope it will be useful.

    To use multiple we need select_tag:

    <%= select_tag "categories", options_from_collection_for_select(Categories.all, 'id', 'name'), :multiple => true %>
    

    Or f.select (many thanks to Tigraine and Brent!), it's more elegant way:

    <%= f.select :categories, Category.all.collect {|x| [x.name, x.id]}, {}, :multiple => true %>
    

    In create action of our controller we need:

    def create
       @post = Post.new(params[:post])
    
    if @post.save
    
      params[:categories].each do |categories|
         categories = PostCategory.new(:category_id => categories, :post_id => @post.id)
         if categories.valid?
           categories.save
         else
           @errors += categories.errors
         end
      end
      redirect_to root_url, :notice => "Bingo!"
    else
      render "new"
    end
    end
    
    0 讨论(0)
提交回复
热议问题