4

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"
Community
  • 1
  • 1
Sasha
  • 6,224
  • 10
  • 55
  • 102
  • 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 Mar 23 '13 at 01:31
  • 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 Mar 23 '13 at 01:46
  • 1
    Negative. You want to specifically build it for your @user object (`@user.build_home`, `@user.build_work`) – awbergs Mar 23 '13 at 01:48
  • How do I refer to that Work/Home object in the view, then? – Sasha Mar 23 '13 at 01:49
  • 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 Mar 23 '13 at 01:50

1 Answers1

3

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

muttonlamb
  • 6,341
  • 3
  • 26
  • 35