Mongoid:'update_attribute'与[models,...] vs与[model_ids,...]

pk1*_*k1m 7 rspec ruby-on-rails mongoid

我正在写一些测试,但我遇到了一些我想要了解的东西.

调用时有什么区别:

.update_attributes(:group_ids, [group1.id, group2.id])
Run Code Online (Sandbox Code Playgroud)

VS

.update_attributes(:groups, [group1, group2])
Run Code Online (Sandbox Code Playgroud)

这两个模型有问题:

group.rb

class Group
  include Mongoid::Document
  has_and_belongs_to_many :users, class_name: "Users", inverse_of: :groups
end
Run Code Online (Sandbox Code Playgroud)

user.rb

class User
  include Mongoid::Document
  has_and_belongs_to_many :groups, class_name: "Group", inverse_of: :users
end
Run Code Online (Sandbox Code Playgroud)

有问题的测试代码:

g1 = create(:group)
u1 = create(:user, groups: [g1])
g1.update_attribute(:users, [u1])
# at this point all the associations look good
u1.update_attribute(:group_ids, [g1.id])
# associations looks good on both sides when i do u1.reload and g1.reload
u1.update_attribute(:groups, [g1])
# g1.reload, this is when g1.users is empty and u1 still has the association
Run Code Online (Sandbox Code Playgroud)

希望我有意义,谢谢

小智 3

  1. 您的所有属性是否已正确列入白名单?

如果没有模型的架构、您的连接对象和我正在​​抓住的实际测试,但纯粹基于该示例,我的猜测是第一个模型包含一个映射到第二个模型上的意外字段的属性,并在传递整个对象时覆盖它,但在指定要更新的属性时不覆盖它。这是一个例子:(我并不是假设您忘记了连接表,我只是使用它,因为它是我首先想到的)

所以我们创建 2 个模型,每个模型都有一个映射到 user_id 的字段

group.create(id:1, user_id:null)
group_user.create(id:1, group_id: 1, user_id:null)

group.update_attributes(user_id: (group_user.id)) 
Run Code Online (Sandbox Code Playgroud)

因此,此时,当您调用 group.users 时,它会检查 id 为 1 的用户,因为这是您刚刚创建并传递它的 group_user 的 id,并假设您的数据库中有一个具有该 ID 的用户,测试通过。

group_user.update_attributes(group_id: group.id) 
Run Code Online (Sandbox Code Playgroud)

在这种情况下,该方法仅更新 group_id,因此一切仍然有效。

group_user.update_attributes(group_id: group, user_id: group) 
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您传递整个对象,并让方法来决定更新哪些字段。我的猜测是,组模型中的某些属性会覆盖用户模型中的相关属性,导致只有当没有 user_ids 与新值匹配时,它才会中断。

或者某个属性未列入白名单,或者您的测试不稳定。