添加具有 nil 值的新动态属性

Add new dynamic attribute with nil value

我在向 mongoid 文档添加值为 nil

的新动态属性时遇到问题
class User
  include Mongoid::Document
  include Mongoid::Timestamps
  include Mongoid::Attributes::Dynamic
end
u = User.find(id)
u.write_attribute(:bar, nil)
puts u.bar
# => nil
u.save!

u = User.find(id)
puts u.bar
# => NoMethodError (undefined method `bar for #<User:0x00007fe87a97cfd8>)

添加具有 nil 以外任何其他值的新属性都可以正常工作。

u = User.find(id)
u.write_attribute(:foo, "a")
puts u.foo
# => "a"
u.save!

u = User.find(id)
puts u.foo
# => "a"

我在这里遗漏了什么吗?

Mongo::Attributes::Dynamic 的文档中提到了这一点:

If the attribute does not already exist on the document, Mongoid will not provide you with the getters and setters and will enforce normal method_missing behavior. In this case you must use the other provided accessor methods: ([] and []=) or (read_attribute and write_attribute).

所以你可以只使用 user[:bar]user.read_attribute(:bar)

您可以使用#set 将属性值设置为零。参见 https://docs.mongodb.com/mongoid/master/tutorials/mongoid-persistence/#atomic

irb(main):024:0> u.set(foo: nil)
D, [2020-10-05T21:31:20.167950 #18418] DEBUG -- : MONGODB | localhost:14400 req:15 conn:1:1 sconn:1088 | mongoid.update | STARTED | {"update"=>"users", "ordered"=>true, "updates"=>[{"q"=>{"_id"=>BSON::ObjectId('5f7bc8642c97a647f27735c6')}, "u"=>{"$set"=>{"foo"=>nil}}}], "$db"=>"mongoid", "lsid"=>{"id"=><BSON::Binary:0x7620 type=uuid data=0x606db89de7a04adf...>}}
D, [2020-10-05T21:31:20.169268 #18418] DEBUG -- : MONGODB | localhost:14400 req:15 | mongoid.update | SUCCEEDED | 0.001s
=> #<User _id: 5f7bc8642c97a647f27735c6, created_at: 2020-10-06 01:29:08.638566093 UTC, updated_at: 2020-10-06 01:29:20.656350934 UTC, bar: nil, bar1: 1, foo: nil>

然后#attributes 按预期工作:

irb(main):023:0> User.find(u.id).attributes
D, [2020-10-05T21:30:18.758322 #18418] DEBUG -- : MONGODB | localhost:14400 req:14 conn:1:1 sconn:1088 | mongoid.find | STARTED | {"find"=>"users", "filter"=>{"_id"=>BSON::ObjectId('5f7bc8642c97a647f27735c6'), "$and"=>[{"_id"=>BSON::ObjectId('5f7bc8642c97a647f27735c6')}]}, "$db"=>"mongoid", "lsid"=>{"id"=><BSON::Binary:0x7620 type=uuid data=0x606db89de7a04adf...>}}
D, [2020-10-05T21:30:18.759791 #18418] DEBUG -- : MONGODB | localhost:14400 req:14 | mongoid.find | SUCCEEDED | 0.001s
=> {"_id"=>BSON::ObjectId('5f7bc8642c97a647f27735c6'), "updated_at"=>2020-10-06 01:29:20.656 UTC, "created_at"=>2020-10-06 01:29:08.638 UTC, "bar1"=>1, "foo"=>nil}

如果您认为 write_attribute 应该保留具有 nil 值的属性,您可以在 https://jira.mongodb.org/browse/MONGOID 创建一个票证来描述您的用例。