从ActiveRecord / Rails查询中检索单个记录
我发出如下的查询,完全检索0或1条记录:
car = Car.where(vin: '1234567890abcdefg')
返回的当然是长度为1的汽车列表。所以我最终在查询结束时添加.first
:
car = Car.where(vin: '1234567890abcdefg').first
好像在Rails中应该有更好的方法。 是否存在类似.onlyOne
东西,只返回一辆Car
并且如果超过1则抛出exception?
car = Car.where(vin: '1234567890abcdefg').onlyOne
要么
car = Car.onlyOne(vin: '1234567890abcdefg')
Rails 4
你想要find_by(vin: 123)
,你可以通过find_by
传递任何字段/值名称的散列来查找。
例如。
Car.find_by(vin: '123')
如果没有找到带有该vin的汽车,或者匹配该vin值的单辆汽车,则返回nil。 如果你添加一个爆炸(即find_by!
),如果没有找到带有该vin的汽车,它将引发exception。
如果您想要在发现多个错误时引发错误,那么您必须自己编写。 如果您不应该遇到多辆汽车具有相同vin的情况,那么最好的方法是使用Car模型的唯一性validation,例如。
class Car < ActiveRecord::Base validates_uniqueness_of :vin # or validates :vin, unique: true end
Rails 3
你想要find_by_vin
(你可以用任何属性的名称替换vin
。
例如。
Car.find_by_vin('123')
如果没有找到带有该vin的汽车,或者具有该vin值的单辆汽车,则返回nil。 如果你添加一个爆炸(即find_by_vin!
),如果没有找到带有该vin的汽车,它将引发exception。
有关更多信息,请访问: http : //guides.rubyonrails.org/active_record_querying.html#retrieving-objects-from-the-database
car = Car.find_by_vin('1234567890abcdefg')
我不认为有什么东西可以抛出一个例外,但是在rails 4中有多个:
car = Car.find_by(vin: '1234567890abcdefg')
将返回唯一的一个。 强制唯一性的最佳方法是在模型/数据库级别上执行:
class Car < ActiveRecord::Base validates :vin, uniqueness: true end
如果由于某种原因,你确实需要在有多辆汽车的情况下抛出exception,你可以在模型上编写一个方法(或猴子补丁活动记录):
class Car < ActiveRecord::Base class << self def only_one!(options) list = where(options) raise "Exactly one car isn't available" if list.size > 1 or list.size == 0 list.first end end end
或使用一个问题:
#lib/active_record_only_one.rb: module ActiveRecordOnlyOne extend ActiveSupport::Concern module ClassMethods def only_one!(options) list = where(options) raise "Exactly one isn't available" if list.size > 1 or list.size == 0 list.first end end end ActiveRecord::Base.send(:include, ActiveRecordOnlyOne)
。
#config/initializers/only_one.rb require "active_record_only_one"
然后打电话:
Car.only_one!(vuid: "1234567890abcdefg")
你可以使用take
and take!
car = Car.where(vin: '1234567890abcdefg').take
如果没有与给定字符串匹配的记录,则返回nil 。
car = Car.where(vin: '1234567890abcdefg').take!
如果没有与给定字符串匹配的记录,则返回ActiveRecord::RecordNotFound
来自指南(1.1.2,1.1.5和1.1.6)
car = Car.take is equivalent to SELECT * FROM cars LIMIT 1