I am totally unable to create a new child in a has_many :through multi
model form using nested_attributes for an existing grandparent.
Sorry, that sounds quite a mouth full.
Basically I am editing an existing user that has many
administrator_addresses through an administrator association.
If I create a new address for the user I get various errors related to
the association between users(grandparent) and
administrator_addresses(grandchild) and I’m wondering how the new
address record(grandchild) get’s the administrator (parent) information?
Grandparent <- Parent <- child
Grandparent has_many :grand_children, :through => :parent, :source =>
:child
If the child validates_presence_of :parent_id I get an error parent must
not be blank.
If I don’t validate the parent id I receive an error stating
Cannot modify association 'User#administrator_addresses' because the
source reflection class ‘Address’ is associated to ‘Administrator’ via
:has_many.
which makes sense if the parent_id has not been passed to the params
hash for the create method.
So how to set the parent ID on the child on a has_many :through multi
model form?
I’m wondering if I have missed something obvious.
Models
class User < ActiveRecord::Base
named_scope :find_administrators, :joins => :administrator
has_one :administrator,
:dependent => :destroy
has_many :administrator_addresses,
:through => :administrator,
:source => :addresses,
:dependent => :destroy
accepts_nested_attributes_for :administrator_addresses,
:allow_destroy => true
…
end
class Administrator < UserRole
belongs_to :user
has_one :site_contact, :foreign_key => :user_role_id
has_many :addresses, :foreign_key => :contact_id, :dependent =>
:destroy
end
class Address < ActiveRecord::Base
belongs_to :administrator, :foreign_key => :contact_id
validates_presence_of :contact_id
validates_presence_of :house
end
class UserRole < ActiveRecord::Base
end
The link helper to build the nested form (slightly different from you
usage)
def add_address_link(form_builder)
link_to_function 'New address' do |page|
form_builder.fields_for :administrator_addresses,
Address.new,
:child_index => 'NEW_RECORD' do |f|
html = render(:partial => 'address_form', :locals => { :f =>
f })
page <<
“jQuery(’#maintenance_form’).replaceWith(’#{escape_javascript(html)}’.replace(/NEW_RECORD/g,
new Date().getTime()))”
end
end
end
The _address_form.html.erb
<fieldset>
<legend>Details...</legend>
<p>
House name/number<br />
<%= f.text_field :house %>
</p>
<p>
Street<br />
<%= f.text_field :street %>
</p>
<p>
Town<br />
<%= f.text_field :town %>
</p>
<p>
city<br />
<%= f.text_field :city %>
</p>
<p>
Postcode<br />
<%= f.text_field :postcode %>
</p>
<%= link_to_function 'Done' %>
The params hash shows
{"user"=>{"name"=>"test2",
"public_name"=>"Test 2",
"password_confirmation"=>"",
"administrator_addresses_attributes"=>{"1249586125635"=>{"city"=>"fff",
"postcode"=>"fff",
"house"=>"fff",
"street"=>"fff",
"town"=>"ffff"}},
"password"=>""},
"commit"=>"Update",
"_method"=>"put",
"authenticity_token"=>"rKa5WGzAcoSDRgBtTA1/RSFp5k4pKQhTCWp1fTRiq6o=",
"id"=>"1"}
The update method in the user controller
def update
logger.debug("#### update params = #{params}")
@user = User.find(params[:id])
respond_to do |format|
if @user.update_attributes(params[:user])
flash[:notice] = "#{show_user_type} was successfully
updated."
format.html { redirect_to([:admin, @user]) }
format.xml { head :ok }
else
format.html { render :action => “edit” }
format.xml { render :xml => @user.errors, :status =>
:unprocessable_entity }
end
end
end
Any ideas would be really cool!
Thanks