4
votes

I'm a little stumped by this one, cause I feel like I've dodged the common errors (like mistyping the attr_accessible, or leaving it out altogether), but I'm still getting a

Can't mass-assign protected attributes: home, work

error here. I'm guessing I'm missing something, but I'm not sure what.

At any rate, in my new app, Users have one Home and one Work (which each belong to a user), and I want users to enter them on signing up. So, in my models:

user.rb

attr_accessible :email, :first_name, :last_name, :password, :password_confirmation, :home_attributes, :work_attributes

  has_one :home, :work

  accepts_nested_attributes_for :work, :home

  has_secure_password

home.rb

attr_accessible :address, :latitude, :longitude, :user_id
belongs_to :user

validates :address, presence: true

work.rb

attr_accessible :address, :latitude, :longitude, :user_id
belongs_to :user

validates :address, presence: true

in my controller

users_controller.rb

def new
    @user = User.new

  respond_to do |format|
    format.html # new.html.erb
    format.json { redirect_to @user }
  end
end

and in my form:

views/users/_form.html.haml

= form_for @user do |f|
  - if @user.errors.any?
    .error_explanation
      %h2
        = pluralize(@user.errors.count, "error") 
        prohibited this post from being saved:
      %ul
        - @user.errors.full_messages.each do |msg|
          %li= msg

  = f.label :first_name
  = f.text_field :first_name

  = f.label :last_name
  = f.text_field :last_name

  = f.label :email
  = f.text_field :email

  = f.label :password
  = f.password_field :password

  = f.label :password_confirmation, "Re-Enter Password"
  = f.password_field :password_confirmation

  = f.fields_for :home do |builder|
    = builder.label :address, "Home address"
    = builder.text_field :address
  %br
  = f.fields_for :work do |builder|
    = builder.label :address, "Work address"
    = builder.text_field :address

  .btn-group
    = f.submit 'Sign Up!', class: "btn"
1
It's curious to me that the error is saying it can't assign home when really the parameter should be named home_attributes. Have you tried doing a @user.build_home and @user.build_work setup in your new action? - awbergs
I tried adding these two lines -- "@home = Home.new" and "@work = Work.new" -- in my controller, then doing "f.fields_for @home do |builder|". Is that what you mean? That protests similarly. - Sasha
Negative. You want to specifically build it for your @user object (@user.build_home, @user.build_work) - awbergs
How do I refer to that Work/Home object in the view, then? - Sasha
You wouldn't do anything different in your form. build_home sets the home property on the @user record so that when you do f.fields_for :home it's referring to what you prepared in the action. - awbergs

1 Answers

3
votes

It looks like you haven't set up your instance variable to include those attributes.

In your controller you should have something like this

def new
    @user = User.new
    @user.homes.build
    @user.works.build

  respond_to do |format|
    format.html # new.html.erb
    format.json { redirect_to @user }
  end
end

If you don't build those attributes the form doesn't know what to do.

Edit: Fixed syntax for building nested resource