Search code examples
ruby-on-railsrubyruby-on-rails-4ruby-on-rails-5

Rails collection_select not getting an id


I'm trying to understand a little more about how the collection_select from Rails form control works.

Items Controller

class ItemsController < ApplicationController
  def index
    @items = Item.all
  end

  def new
    @item = Item.new
    @categories = Category.all
  end

  def create
    @item = Item.new(params.require(:item).permit(:name, :description, :category))
    render plain: @item.inspect
    # @item.save
    # redirect_to my_page_path
  end

  def show
    @item = Item.find(params[:id])
  end
end

HTML

<div class="form-group">
    <%= f.label :category %>
     <%= f.collection_select(:category_ids, Category.all, :id, :name,
            { prompt: "Make your selection from the list below"}, { multiple: false, size: 1, class: "custom-select shadow rounded" }) %>
  </div>

When I render the code I get category_id = nil

#<Item id: nil, name: "Yo", description: "Brand new", created_at: nil, updated_at: nil, category_id: nil>

Thank you.... any help with some explanation would be much appreciated.


Solution

  • I see two issues in the code. You already noticed that the category_id is nil on the object.

    Looking at the form the collection_select helper sets a category_ids, but your model's attribute is named category_ids. Just remove the plural s

    <%= f.collection_select(:category_id, Category.all, :id, :name,
            # ... %>
    

    The other issue is the configuration of the StrongParameters in the controller. Strong params methods are working on the params hash and do not know that a category association exists and that this association works with a category_id. Therefore your need to be precise and add category_id to the list:

    def create
      @item = Item.new(params.require(:item).permit(:name, :description, :category_id))
      render plain: @item.inspect
      # @item.save
      # redirect_to my_page_path
    end