如何发出引发RecordNotFound的'find'或'where'

ber*_*kes 9 activerecord ruby-on-rails-3

当我使用id调用find时,它将成为目标查找,并将抛出错误RecordNotFound.

Foo::Bar.find(123) # RecordNotFound if no Bar with id 123 exists.
Run Code Online (Sandbox Code Playgroud)

但是当我用条件调用它时,如果没有找到,我会得到nil:

Foo::Bar.find(:first, :conditions => [ "lower(name) = ?", name.downcase ])
Run Code Online (Sandbox Code Playgroud)

我想要这样的条件搜索也会引发错误.我知道我能做到:

Foo::Bar.find_by_name!("CocktailBar") #=> raises Recordnotfount if not not found.
Run Code Online (Sandbox Code Playgroud)

但那只有非常简单的条件.我需要更多的复杂性; 实际上是这样的:

Foo.Bar.select{ |pm| pm.name.downcase =~ /cocktail/}.first
Run Code Online (Sandbox Code Playgroud)

并且,如果找不到任何内容,我希望它引发RecordNotFound错误.这有可能吗?或者我应该简单地添加一些代码来检查nil?如果没有?自己提出错误?如果是这样,我如何在Rails 3中做到这一点?

Roc*_*etR 45

在最后一段代码中,您实际上从DB获取所有记录,然后select在Ruby数组上执行.它与之无关ActiveRecord,所以你可以做任何你想做的事情来手动引发异常,要么使用道格拉斯建议的代码if,要么unless等等.但是你似乎不太了解你的代码做了什么.你select {...}没有被翻译成SQL SELECT ... WHERE(...).

如果您需要通过ActiveRecord查询自动引发异常,请使用以下命令:

Foo::Bar.where([ "lower(name) = ?", name.downcase ]).first!
Run Code Online (Sandbox Code Playgroud)

例如,对于find_by方法也存在等效的爆炸方法 Foo::Bar.find_by_name!(name)

  • IMO这是一个比接受的答案更好的答案.:) (6认同)
  • 从来不知道`first!`方法,谢谢你提到它. (3认同)

Lay*_*ira 6

对于遇到这个问题的任何人来说,现在您拥有了find_by! 完全符合OP对该find案例要求的方法。

例子:

Foo::Bar.find_by!(name: "CocktailBar")
Run Code Online (Sandbox Code Playgroud)

https://apidock.com/rails/v4.0.2/ActiveRecord/FinderMethods/find_by%21


Dou*_*rer 3

你的最后一段就是你需要做的。要么检查 nil,要么自己引发异常。要自行引发异常,请执行以下操作:

Foo::Bar.find(:first, :conditions => [ "lower(name) = ?", name.downcase ]) || raise(ActiveRecord::RecordNotFound)
Run Code Online (Sandbox Code Playgroud)