Richard G
Richard G

Reputation: 5693

can't mass assign nested attributes

I've checked a few answers to similar problems, and all seem to suggest the problem is attr_accessible, but I just can't seem to get this working.

Basically I have User & Address model,and want to assign Address attributes as nested attributes. But when I save it causes the can't mass-assign attributes error shown below.

I've tried many variations of attr_accessible in below code, like :addresses_attributes, :address_attributes, :primary_address_attributes...I'm not sure why it's not working,perhaps because it's in the Member module declaration??

Can anyone help?

class Member::User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :token_authenticatable, :confirmable,
  # :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
  :recoverable, :rememberable, :trackable, :validatable

  # each user may have zero or many addresses
  # their primary email is also set as their login id.
  has_many :addresses

  has_one :address, :class_name => "Member::Address", :conditions => "is_primary = true"
  accepts_nested_attributes_for :addresses, :address

  # Setup accessible (or protected) attributes for your model
  attr_accessible :email, :password, :password_confirmation, :remember_me,     :address_attributes

   validates_presence_of :email 

end

My form that submits the nested fields (relevant parts of)

  <%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => {:class => "form-horizontal"}) do |f| %>
    <small>Mandatory fields marked *</small><br><br>
    <% devise_error_messages! %>
    <% flash.each do |name, msg| %>
      <div class="alert alert-<%= name == :notice ? "success" : "error" %>">
        <a class="close" data-dismiss="alert">×</a>
        <%= msg %>
      </div>
    <% end %>

    <%= f.fields_for resource.build_primary_address do |address_form| %> 
    <div class="control-group">
        <%= address_form.label :first_name, :class => "control-label" %>
        <div class="controls">
          <%= address_form.text_field :first_name, :class => "input-xlarge" %>
        </div>
      </div>

    <div class="control-group">
        <%= address_form.label :last_name, :class => "control-label" %>
        <div class="controls">
          <%= address_form.text_field :last_name, :class => "input-xlarge" %>
        </div>
      </div>
    <% end %>

The error shows this:

 Can't mass-assign protected attributes: member_address

{"utf8"=>"✓",
 "authenticity_token"=>"HrZJG2krn15veUKJVh6PgEs4wwufaeRhciHcUIn6AaM=",
 "user"=>{"member_address"=>{"first_name"=>"asdf",
 "last_name"=>"asdfsafd"},
 "email"=>"[email protected]",
 "password"=>"[FILTERED]",
 "password_confirmation"=>"[FILTERED]"}}

Upvotes: 0

Views: 297

Answers (2)

cdesrosiers
cdesrosiers

Reputation: 8892

In order for rails to understand that that the primary address being submitted in the form is a nested attribute, you have to explicitly tell it the relation here:

<%= f.fields_for :address, resource.build_primary_address do |address_form| %>

. The reason is, because your model names are scoped with Member::, and rails derives form parameter names from the class names, in your params hash you end up with :member_address instead of :address. Because :address in this case is a field for which :user accepts nested attributes, :address should be represented as :address_attributes in the params hash, so make sure the latter appears in attr_accessible.

Upvotes: 1

Erez Rabih
Erez Rabih

Reputation: 15788

Add

attr_accessible :member_address

to the User model.

Explanation: every hash key that you want to initialize an ActiveRecord instance with must be stated as attr_accessible. Looking at your hash keys there is:

 "user"=>{"member_address"=>{ ... }}

member_address key in the hash which initializes the User instance, thus it has to be included in the attr_accessible statement.

Upvotes: 0

Related Questions