gtheys
gtheys

Reputation: 521

strong parameters has_many through

Trying to figure out why the setter doesn't work on:

class Company < ActiveRecord::Base
  has_many :memberships 
  has_many :users, :through => :memberships, dependent: :destroy

end

class Membership < ActiveRecord::Base
  belongs_to :user
  belongs_to :company

  validates_presence_of :user
  validates_presence_of :company

end

class User < ActiveRecord::Base
  has_many :memberships
  has_many :companies, :through => :memberships, dependent: :destroy
  accepts_nested_attributes_for :companies
end

<%= form_for(@user) do |f| %>
  <% if @user.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@user.errors.count, "error") %> prohibited this user from being saved:</h2>

      <ul>
      <% @user.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.fields_for :company do |ff|%>
      <%= ff.label :name %><br>
      <%= ff.text_field :name %>
    <% end %>
  </div>

  <div class="field">
    <%= f.label :name %><br>
    <%= f.text_field :name %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

# Never trust parameters from the scary internet, only allow the white list through.
def user_params
  params.require(:user).permit(:name, companies_attributes:[:name])
end

it works when I do:

# Never trust parameters from the scary internet, only allow the white list through.
def user_params
  params.require(:user).permit(:name, company:[:name])
end

So for me it's not quite clear as the documentation says the setter companies_attributes is ceated when accepts_nested_attributes_for :companies

Upvotes: 2

Views: 2162

Answers (1)

Doon
Doon

Reputation: 20232

When using fields_for with accepts_nested_attributes_for they need to match. see http://apidock.com/rails/ActionView/Helpers/FormHelper/fields_for

you have accepts_nested_attributes_for :companies but f.fields_for :company hence the disconnect.

So try changing your form to include

<div class="field">
    <%= f.fields_for :companies do |ff|%>
      <%= ff.label :name %><br>
      <%= ff.text_field :name %>
    <% end %>
  </div>

and your user_params method to be

def user_params
  params.require(:user).permit(:name, companies_attributes:[:name])
end

Which should cause them to be populated under companies_attributes and your original user_params method to work. as the fields_for should generate user[companies_attributes[id][name]] since user has_many companies (do you want to include multiple companies in the list to be created?)

Upvotes: 2

Related Questions