等价于 create_with 的 Mongoid

Mongoid equivalent of create_with

是否有等效的 Active Records Model.create_with 来传递与 Mongoid 中的查找参数分开的创建参数?

# Find the first user named "Scarlett" or create a new one with
# a particular last name.
User.create_with(last_name: 'Johansson').find_or_create_by(first_name: 'Scarlett')
# => #<User id: 2, first_name: "Scarlett", last_name: "Johansson">

我发现自己使用了一个笨拙的解决方法:

user = User.find_or_initialze_by(first_name: 'Scarlett')
user.update(last_name: 'Johansson') if user.new_record?

Mongoid 的 find_or_create_by takes an optional block which is only used when it needs to create something. The documentation isn't exactly explicit about this behavior but if you check the code you'll see that find_or_create_by ends up as a call to this find_or 方法:

def find_or(method, attrs = {}, &block)
  where(attrs).first || send(method, attrs, &block)
end

其中 method:create,如果您要查找的文档被 where 找到,则不使用 block

这意味着你可以说:

user = User.find_or_create_by(first_name: 'Scarlett') do |user|
  user.last_name = 'Johansson'
end

获得您想要的效果。

大概这种 "the create half uses the block" 行为应该是显而易见的,因为 create 需要一个块来初始化对象,但 find 不会。

如果您对这种未记录的行为感到疑惑,您可以在您的规范中包含对它的检查,这样您至少会知道升级何时会破坏它。