marcamillion
marcamillion

Reputation: 33755

Select statement in a form partial for an HABTM association

I have two models Client and Topic. Both of which have a HABTM association between them.

I am trying to add a select statement in my _form partial in my Client views, that allows the user to add a topic to a client (or edit that topic, etc.).

This is what my form partial looks like:

<%= form_for(@client) do |f| %>

  <div class="field">
    <%= f.label :topic %><br />
    <%= f.select :topics, Topic.all.collect { |topic| [topic.name, topic.id] }, {:include_blank => 'None'} %>
  </div>

  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

The first error I got was this:

ActiveModel::MassAssignmentSecurity::Error in ClientsController#create

Can't mass-assign protected attributes: topics

So, in my Client model, I added this:

attr_accessible :email, :firm_id, :name, :phone, :topics

This is the error I now get:

NoMethodError in ClientsController#create

undefined method `each' for "1":String

The create action of my Clients controller is very standard:

  def create
    @client = Client.new(params[:client])

    respond_to do |format|
      if @client.save
        format.html { redirect_to @client, notice: 'Client was successfully created.' }
        format.json { render json: @client, status: :created, location: @client }
      else
        format.html { render action: "new" }
        format.json { render json: @client.errors, status: :unprocessable_entity }
      end
    end
  end

These are the params submitted (notice that topics is being passed - instead of topic_id but topic_id doesn't work either):

{"utf8"=>"✓",
 "authenticity_token"=>"J172LuZQc5NYoiMSzDD3oY9vGmxxCX0OdxcGm4GSPv8=",
 "client"=>{"name"=>"Jack Daniels",
 "email"=>"[email protected]",
 "phone"=>"2345540098",
 "firm_id"=>"2",
 "topics"=>"1"},
 "commit"=>"Create Client"}

How can I get a topic assigned to my client on the creation of the client with this select statement?

Thanks!

Upvotes: 0

Views: 347

Answers (1)

Niko Efimov
Niko Efimov

Reputation: 2213

When setting a "Topic" attribute, Client expects an instance of a Topic class.

Since you are passing IDs, you need to change:

<%= f.select :topics, Topic.all.collect { |topic| [topic.name, topic.id] }, {:include_blank => 'None'} %>

to set topic_ids instead:

<%= f.select :topic_ids, Topic.all.collect { |topic| [topic.name, topic.id] }, {:include_blank => 'None'} %>

And, of course, in attr_accessible:

attr_accessible :email, :firm_id, :name, :phone, :topic_ids

Upvotes: 1

Related Questions