Rails:3.0.11
Ruby:1.9.3
当我更新父对象时,为什么活动记录update_attribute对对象(父对象)的关联对象(子对象)执行DELETE查询? 的
以下是我的课程:
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
在前端,每个关键字都有一个复选框。
我第一次选中“关键字1”和“关键字2”复选框来更新用户的关键字。
我再次编辑用户通过选中“关键字1”和“关键字3”复选框更新关联的关键字并更新用户。 第二次更新删除了我的USER_KEYWORDS表中的先前记录。
以下是我的控制台输出,显示正在执行的DELETE语句:
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')
has_many方法的:dependent选项说(http://guides.rubyonrails.org/association_basics.html#has_many-association-reference):
如果将:dependent选项设置为:destroy,则删除此对象将调用关联对象上的destroy方法以删除这些对象。如果将:dependent选项设置为:delete_all,则删除此对象将删除关联的对象而不调用其destroy方法。如果将:dependent选项设置为:nullify,则删除此对象会将关联对象中的外键设置为NULL。
在关联上使用:through选项时,将忽略此选项。 ##
我无法理解这种行为。任何人都可以详细说明或澄清一下吗?
答案 0 :(得分:3)
delete语句仅删除了关键字2的关联。当您提交了选中了两个复选框的表单时,系统会假定您希望这两个项目关联,但没有其他项目未检查。因此,当它加载当前的user_keyword
关联时,它看到有一个您没有选择保留的现有记录,因此将其删除。然后它看到有一个新的,所以它创建了一个新的。
如果你只想添加关系,而不是删除关系,那么我不推荐复选框,因为选中复选框意味着添加,但删除支票意味着破坏关系(这是rails在这种情况下所做的)。具有AJAX功能的按钮可能更有意义。如果你确实想要保留复选框,但不允许rails来破坏未被选中的关系,那么你必须根据参数自己建立关系,而不是依靠rails magic来为你完成这项工作。< / p>
请注意,这与:dependent
选项无关,这仅仅是由于您在模型和表单中设置的关系。