问题
Rails: 3.0.11
Ruby: 1.9.3
Why does active record update_attribute executes a DELETE query on an associated object(child) of an object(parent) when I updated the parent?
Following are my classes:
class User < ActiveRecord::Base
has_many :user_keywords, :dependent => :destroy
has_many :keywords, :through => :user_keywords
end
class UserKeyword < ActiveRecord::Base
belongs_to :user
belongs_to :keyword
end
class Keyword < ActiveRecord::Base
has_many :user_keywords
has_many :users, :through => :user_keywords
end
On front-end I have a checkbox for each keyword.
- Checkbox: Keyword 1
- Checkbox: Keyword 2
- Checkbox: Keyword 3
- Checkbox: Keyword 4
First time I checked "Keyword 1" and "Keyword 2" checkboxes to update the user's keywords.
I again edited the user to update the associated keywords by checking "Keyword 1" and "Keyword 3" checkboxes and updated the user. The second updated deleted the previous records in my USER_KEYWORDS table.
Following is my console output showing the DELETE statement being executed:
User Load (55.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = 5 LIMIT 1
Keyword Load (0.2ms) SELECT "keywords".* FROM "keywords" WHERE "keywords"."id" IN (1, 3)
Keyword Load (0.2ms) SELECT "keywords".* FROM "keywords" INNER JOIN "user_keywords" ON "keywords".id = "user_keywords".keyword_id WHERE (("user_keywords".user_id = 5))
AREL (0.2ms) DELETE FROM "user_keywords" WHERE "user_keywords"."user_id" = 5 AND "user_keywords"."keyword_id" = 2
AREL (0.1ms) INSERT INTO "user_keywords" ("keyword_id", "user_id", "status", "created_at", "updated_at") VALUES (3, 5, 'f', '2012-06-12 13:15:43.912236', '2012-06-12 13:15:43.912236')
The :dependent option on has_many method says (http://guides.rubyonrails.org/association_basics.html#has_many-association-reference):
4.3.2.6 :dependent
If you set the :dependent option to :destroy, then deleting this object will call the destroy method on the associated objects to delete those objects. If you set the :dependent option to :delete_all, then deleting this object will delete the associated objects without calling their destroy method. If you set the :dependent option to :nullify, then deleting this object will set the foreign key in the associated objects to NULL.
This option is ignored when you use the :through option on the association. ##
I am unable to understand this behavior.Can anybody please elaborate or clarify in this?
回答1:
The delete statement only deleted the the association for keyword 2. When you submitted the form with two checkboxes checked, the system assumes that you want those two items associated, but none of the others that were not checked. Therefore, when it loaded the current user_keyword associations, it saw that there was one existing record that you did not choose to keep, so it deleted it. It then saw that there was one new one, so it created a new one.
If you want to only add relationships, and not remove relationships, then I would not recommend checkboxes, as checking a checkbox implies adding, but removing a check implies destroying the relationship (which is what rails did in this case). A button with AJAX functionality might make more sense. If you do want to keep checkboxes, but not allow rails to destroy relationships that weren't selected, then you would have to build the relationships yourself based on the parameters, and not rely on the rails magic to do the job for you.
Note that this is not related to the :dependent option, this is simply due to the relationship you have set up in the models and in the form.
来源:https://stackoverflow.com/questions/10997990/active-record-update-attribute-executes-a-delete-query-on-an-associated-objectc