3

导轨:3.0.11

红宝石: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
  • 复选框:关键字 3
  • 复选框:关键字 4

第一次我检查了“关键字 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):

4.3.2.6:依赖

如果将 :dependent 选项设置为 :destroy,则删除此对象将调用关联对象的 destroy 方法以删除这些对象。如果将 :dependent 选项设置为 :delete_all,则删除此对象将删除关联的对象,而无需调用它们的 destroy 方法。如果将 :dependent 选项设置为 :nullify,则删除此对象会将关联对象中的外键设置为 NULL。

当您对关联使用 :through 选项时,将忽略此选项。##

我无法理解这种行为。有人可以详细说明或澄清吗?

4

1 回答 1

3

删除语句只删除了关键字 2 的关联。当您提交带有两个复选框的表单时,系统假定您希望关联这两个项目,但没有选中其他项目。因此,当它加载当前user_keyword关联时,它看到有一条您没有选择保留的现有记录,因此将其删除。然后它看到有一个新的,所以它创建了一个新的。

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.

于 2012-06-12T14:39:47.733 回答