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

时间:2013-11-05 17:25:49

标签: ruby-on-rails activerecord

在Django中,ORM有一个名为get()的函数,用于仅返回模型的单个实例。具体来说,如果在你只期望一个的情况下返回多个对象,会引发一个异常,所以它对于某些查找很有用(即“查找带有这个slug的一篇文章”)。

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

Model.where( ... ).first

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

Active Record Query Interface guide列出了5种检索单个对象的方法,其中find()find_by()看起来最有希望,但当多个对象与搜索条件匹配时,它们都不会引发异常。

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

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

2 个答案:

答案 0 :(得分: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

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

答案 1 :(得分:2)

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

似乎完全符合要求:

<块引用>

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

用例很简单:

Model.find_sole_by(conditions: 'here')