Bastien
Bastien

Reputation: 606

Rails form helper adding an associated model through collection_select

I have troubles adding an associated model through a collection_select method. Here are my two models

class Signatory < ActiveRecord::Base
belongs_to :bank
end

and

class Bank < ActiveRecord::Base
has_many :signatories
end

I have some banks already added in my "banks" table and I want to add a signatory with the associated bank_id field populated through a drop-down list. Here the code of the form:

<%= form_for(@signatory) do |f| %>
  <%= f.label :bank_id %>
  <%= f.collection_select(:bank, Bank.all, :id, :name %>

  <%= f.label :first_name %>
  <%= f.text_field :first_name %>
  <%#-...   %>
<%= f.submit "Add signatory" %>
<% end %>

These are the relevant parts of my controllers:

def new
  @signatory = Signatory.new
end
def create
  @signatory = bank.signatories.build(signatory_params)
  @signatory.save
end

The console shows the following hash which is what I expect:

Parameters: {... "signatory"=>{"bank_id"=>"1", "first_name"=>"Al", "last_name"=>"Smith", "email"=>"Al@"}, "commit"=>"Add signatory"}

However, I get the error message undefined local variable or method 'bank'. If I add the line

    bank = Bank.find(1)

in the create action, it would work, obviously. How/When/where do I define the 'bank' variable? What am I missing in the controller to have the form pass the 'bank_id' attribute to the 'bank' variable and then save it into my signatory table? Thanks.

Upvotes: 1

Views: 1213

Answers (2)

cainlevy
cainlevy

Reputation: 181

You can set the bank variable from those parameters like this:

def create
  bank = Bank.find(params[:signatory][:bank_id])
  @signatory = bank.signatories.build(signatory_params)
  @signatory.save
end

But this is unnecessary. It's simpler to create the signatory directly, e.g.:

def create
  @signatory = Signatory.new(signatory_params)
  @signatory.save
end

The bank.signatories.build pattern you are following is more helpful when you know the bank from another parameter in the hash or URL and you want to supplement a parameter that was not present in the form. In this case the only available parameter comes directly from the form (params[:signatory][:bank_id]).

Upvotes: 1

Andrey Turkin
Andrey Turkin

Reputation: 719

It's incorrect use of collection_select helper here:

<%= f.collection_select(:bank, Bank.all, :id, :name %>

Rewrite as:

<%= f.collection_select :bank_id, Bank.all, :id, :name %>

Also where's the bank variable gets defined here:

 def create
  @signatory = bank.signatories.build(signatory_params)

Do you have some before_action which is not shown?

Upvotes: 0

Related Questions