Nested Attributes not updating
With the following models:
class Location < ActiveRecord::Base
has_many :group_locations
has_many :groups, :through =&开发者_JAVA技巧gt; :group_locations
accepts_nested_attributes_for :group_locations
end
class GroupLocation < ActiveRecord::Base
belongs_to :group
belongs_to :location
end
class Group < ActiveRecord::Base
has_many :group_locations
has_many :locations, :through => :group_locations
end
the following commands in rails console does not update the associated records:
>> l = Location.find(1)
=> #<Location id: 1, phone: "(949) 788-9999", ... created_at: "2011-06-02 00:58:07",
updated_at: "2011-06-07 23:57:32">
\>\> l.group_locations
=> [#<GroupLocation group_id: 4, location_id: 1, created_at: "2011-06-02 00:58:07",
updated_at: "2011-06-02 00:58:07">, #<GroupLocation group_id: **37**, location_id: 1,
created_at: "2011-06-02 00:58:07", updated_at: "2011-06-02 00:58:07">]
>> l.update_attributes(:phone => "(949) 788-9998", :group_locations_attributes =>
[{:group_id => 4, :location_id => 1}, {:group_id => **38**, :location_id => 1}])
=> true
>> l
=> #<Location id: 1, phone: "(949) 788-9998", ... created_at: "2011-06-02 00:58:07",
updated_at: "2011-06-08 02:05:00">
>> l.group_locations
=> [#<GroupLocation group_id: 4, location_id: 1, created_at: "2011-06-02 00:58:07",
updated_at: "2011-06-02 00:58:07">, #<GroupLocation group_id: **37**, location_id: 1,
created_at: "2011-06-02 00:58:07", updated_at: "2011-06-02 00:58:07">]
Note that the update_attributes call attempts to change the second GroupLocation to have group_id = 38, but the change is not made (even though the phone number did change). After looking at the code generated when this was implemented in the controller and view, changing the array to a hash (which is what is created in that case) has no different results (and the form/controller) have the same effect of not updating the associated records even though the main record is updated.
Any idea what I need to do to get the nested attributes to update?
From the logs you've displayed, it doesn't appear that your GroupLocation model has an :id primary key on it. While the join table for a HABTM has just the foreign keys (group_id, location_id) on it, the model used for a has_many :through association does need a primary key as well, :id by default. Otherwise, there is no way to determine which of the child objects to update in the case of an update.
Think of it this way - you are creating your association through another discrete model that should be able to stand entirely on its own.
The convention for nested attributes is if the hash passed to the nested_attributes includes an :id, then it is considered an update, if it doesn't then it's considered a create. In your case, you're not passing in an :id, so you get new GroupLocation records where you just wanted to update existing.
I believe, also, that once you have this in place correctly, you will be able to get rid of the attr_accessible, I don't think that should be necessary.
For good info on the nested attributes functionality that covers most of this, check out this page.
The actual answer is that the nested attributes must be accessible via attr_accessible. "accepts_nested_attributes" will only do what I want if it is accompanied by "attr_accessible :group_locations".
精彩评论