Rails方法仅返回单个记录并在返回多个时抛出异常

Har*_*ody 11 activerecord ruby-on-rails

在Django中,ORM有一个函数get(),用于仅返回模型的单个实例.具体来说,如果在您只预期一个对象时返回多个对象,则会引发异常,因此对于某些查找(即"查找带有此slug的一篇文章")非常有用.

我无法在Rails/ActiveRecord中找到具有相同行为的类似函数.到目前为止,我刚刚编写的代码如下:

Model.where( ... ).first
Run Code Online (Sandbox Code Playgroud)

但这导致了一个无声的错误,其中一个对象的多个实例被返回 - 这实际上是一个糟糕的,模棱两可的情况 - 我们只是抓住了第一个并继续进行,就像一切都好.

" 活动记录查询接口"指南列出了5种检索单个对象的方法,find()并且find_by()看起来最有希望,但是当多个对象与搜索条件匹配时,它们都不会引发异常.

我知道我可以编写where()find_by()查询并检查自己返回的对象数量,但是这些代码出现在我们的代码库中的任何地方,我宁愿不添加所有这些内容.它似乎也是一种普遍的,普遍的需求,我希望它可以在某个地方融入Rails/ActiveRecord.

是否有一些我缺少的功能可以让你更容易捕捉到这些情况?如果有帮助,我们正在使用Rails 4和Ruby 2.0.

SRa*_*ack 9

Rails 7.0为此引入了find_sole_by(或)。where(...).sole

似乎完全符合要求:

查找唯一匹配的记录。ActiveRecord::RecordNotFound如果未找到记录则引发。ActiveRecord::SoleRecordExceeded如果找到多个记录则引发。

用例很简单:

Model.find_sole_by(conditions: 'here')
Run Code Online (Sandbox Code Playgroud)


Jos*_*osh 2

我不知道内置的 Active Record 方法可以满足您的要求,但编写您自己的方法并不难。就像是:

class YourModel
  def self.find_only_one_by_slug(slug)
    results = YourModel.where(slug: slug)
    if results.size > 1
      raise "There should only be one return value."
    else
      return results.first
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

我还没有测试过上面的代码,所以肯定会有错误,但你明白了。您甚至可以更进一步,向所有模型都可以访问的活动记录库添加类似的方法。