I thought I had this fixed, but apparently not. It works okay from the
console, but not from the view. I have the following:
# partial schema
create_table "users", :force => true do |t|
t.string "login", :null => false
t.string "first_name"
t.string "last_name"
t.string "email", :null => false
t.string "password", :null => false
t.integer "contact_id"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "contacts", :force => true do |t|
t.string "company_name"
t.integer "address_id"
t.integer "phone_areacode", :limit => 3
t.integer "phone_prefix", :limit => 3
t.integer "phone_suffix", :limit => 4
t.integer "phone_extension", :limit => 5
t.string "website"
t.integer "biztype_id"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "addresses", :force => true do |t|
t.string "street_address1"
t.string "street_address2"
t.string "city"
t.integer "state_id"
t.integer "zipcode"
t.integer "plus4"
t.datetime "created_at"
t.datetime "updated_at"
end
# relevant models
class User < ActiveRecord::Base
belongs_to :contact
has_many :properties
has_many :notes, :through => :properties
accepts_nested_attributes_for :contact, {
:allow_destroy => true,
:reject_if => :all_blank
}
end
class Contact < ActiveRecord::Base
has_one :user
belongs_to :address
belongs_to :biztype
accepts_nested_attributes_for :address, {
:allow_destroy => true,
:reject_if => :all_blank
}
end
class Address < ActiveRecord::Base
has_one :contact
has_one :property
belongs_to :state
end
# controller
def new
@user = User.new
@user.build_contact.build_address
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => @user }
end
end
def edit
@user = User.find(params[:id])
end
When I run on the console, I can create a new user object with nested
attributes like so:
>> user=User.new
=> #<User id: nil, login: nil, first_name: nil, last_name: nil, email: nil, password: nil, contact_id: nil, created_at: nil, updated_at: nil>
>> user.build_contact.build_address
=> #<Address id: nil, street_address1: nil, street_address2: nil, city: nil, state_id: nil, zipcode: nil, plus4: nil, created_at: nil, updated_at: nil>
>> user.login, user.password, user.email = 'foo', 'bar', 'baz'
=> ["foo", "bar", "baz"]
>> user.contact.company_name, user.contact.address.city = 'foobar', 'foobaz'
=> ["foobar", "foobaz"]
>> user.save
=> true
>> p user, user.contact, user.contact.address
#<User id: 4, login: "foo", first_name: nil, last_name: nil, email: "baz", password: "bar", contact_id: 2, created_at: "2009-11-06 02:33:41", updated_at: "2009-11-06 02:33:41">
#<Contact id: 2, company_name: "foobar", address_id: 3, phone_areacode: nil, phone_prefix: nil, phone_suffix: nil, phone_extension: nil, website: nil, biztype_id: nil, created_at: "2009-11-06 02:33:41", updated_at: "2009-11-06 02:33:41">
#<Address id: 3, street_address1: nil, street_address2: nil, city: "foobaz", state_id: nil, zipcode: nil, plus4: nil, created_at: "2009-11-06 02:33:41", updated_at: "2009-11-06 02:35:09">
=> nil
As you can see, it appears to work fine, but the following views for
new.html.erb and edit.html.erb don't:
<h1>New account</h1>
<% form_for(@user) do |f| %>
<%= f.error_messages %>
<p> <%= f.label :login %>: <%= f.text_field :login %> </p>
<p> <%= f.label :first_name %>: <%= f.text_field :first_name %> </p>
<p> <%= f.label :last_name %>: <%= f.text_field :last_name %> </p>
<p> <%= f.label :email %>: <%= f.text_field :email %> </p>
<p> <%= f.label :password %>: <%= f.password_field :password %> </p>
<% fields_for(@contact) do |f| %>
<%= f.error_messages %>
<p> <%= f.label :company_name %>: <%= f.text_field :company_name %> </p>
<p> <%= f.label :Type_of_Organization %>: <%= f.text_field :biztype_id %> </p>
<% fields_for(@address) do |f| %>
<%= f.error_messages %>
<p> <%= f.label :street_address1 %>: <%= f.text_field :street_address1 %> </p>
<p> <%= f.label :street_address2 %>: <%= f.text_field :street_address2 %> </p>
<p> <%= f.label :city %>: <%= f.text_field :city %> </p>
<p> <%= f.label :state_id %>: <%= f.text_field :state_id, :maxlength=>2 %> </p>
<p> <%= f.label :zipcode %>: <%= f.text_field :zipcode, :maxlength=>5 %>-<%= f.text_field :plus4, :maxlength=>4 %> </p>
<% end %>
<p> <%= f.label :phone %>: (<%= f.text_field :phone_areacode, :maxlength=>3 %>) <%= f.text_field :phone_prefix, :maxlength=>3 %>-<%= f.text_field :phone_suffix, :maxlength=>4 %> Ext. <%= f.text_field :phone_extension, :maxlength=>5 %> </p>
<p> <%= f.label :website %>: <%= f.text_field :website %> </p>
<% end %>
<p> <%= f.submit 'Create' %> </p>
<% end %>
<%= link_to 'Back', accounts_path %>
The view doesn't create the additional table entries, nor does it allow
me to edit anything but the unjoined data (e.g. @users, not
@users.contact). Obviously I'm still missing something important here. I
want to be able to both populate *and* edit this content from
similarly-nested views.
Why does this work from the console, but not from within the web app
itself?