Search code examples
ruby-on-railsruby-on-rails-4nested-attributes

Weird behavior with nested params


I'm experiencing this weird behavior with nested params. When I try to save the form it says Unpermitted parameter: organization_type

For my organization type I only have a model but I don't think that should be the issue because the attributes are being handled in the user controller, per my understanding

I tried to have the attributes as organization_type (singular) in both form and controller white list but that does not work.

However, in the form, if I have :organization_types the field will not show up.

I'm really puzzled by this.

So as a quick recap:

  • I do not have a controller for OrganizationType
  • In the form I have: :organization_type. If I pluralize it does not show
  • In the Controller white list I have: :organization_types_attributes
  • In the User Model I have: Has_many and accepts_nested for :organization_types_attributes

User Model

class User < ActiveRecord::Base
  has_many :events
  has_many :organization_types
  accepts_nested_attributes_for :organization_types
end

Organization Types Model

class OrganizationType < ActiveRecord::Base
  belongs_to :user
  ORG_TYPES = ['health', 'non-profit', 'foo', 'bar']
end

User Controller

class UsersController < ApplicationController
  before_action :set_user, only: [:show, :edit, :update, :destroy]
  before_filter :authenticate_user!

  ...

  def user_params
      params.require(:user).permit(:name, ..., organization_types_attributes: [:id, :user_id, :org_type, '_destroy'])
  end

User Form

<%= form_for(@user) do |f| %>
  ...
  <div class="field">
    <%= f.label :organization_type %><br>
    <%= f.fields_for :organization_type do |builder| %>
      <%= builder.select :org_type, options_for_select(OrganizationType::ORG_TYPES) %><br/>
    <% end %>
  </div>
<% end %>

Solution

  • It should be :organization_types in your nested form:

    <%= f.fields_for :organization_types do |builder| %>
      <%= builder.select :org_type, options_for_select(OrganizationType::ORG_TYPES) %><br/>
    <% end %>
    

    The reason that you found that the form does not show with the pluralized organization_types is that Rails will not render the nested attributes in the form if the user has no organization_types yet. I would check out the very helpful Rails guide on nested forms, section 9.2. To quote that source, which uses the example of a Person object that has_many addresses and accepts_nested_attributes_for addresses:

    When an association accepts nested attributes fields_for renders its block once for every element of the association. In particular, if a person has no addresses it renders nothing. A common pattern is for the controller to build one or more empty children so that at least one set of fields is shown to the user. The example below would result in 2 sets of address fields being rendered on the new person form...

    Example from the guide, adapted for your controller:

    def new   
      @user = User.new
      2.times { @user.organization_types.build}
    end
    

    See if that helps...