我发出如下所示的查询,完全检索0或1条记录:
car = Car.where(vin: '1234567890abcdefg')
返回的内容当然是长度为1的汽车列表。所以我最终在查询结尾处添加了.first
:
car = Car.where(vin: '1234567890abcdefg').first
似乎在Rails中应该有更好的方法。是否存在类似.onlyOne
的内容,只返回一个Car
并在超过1时抛出异常?
car = Car.where(vin: '1234567890abcdefg').onlyOne
或
car = Car.onlyOne(vin: '1234567890abcdefg')
答案 0 :(得分:1)
car = Car.find_by_vin('1234567890abcdefg')
答案 1 :(得分:1)
你想要find_by(vin: 123)
,你可以传递find_by
任何字段/值名称的哈希来查找。
例如
Car.find_by(vin: '123')
如果没有找到带有该vin的汽车,或者与该vin值匹配的单辆汽车,则返回nil。如果你添加一个爆炸(即find_by!
),如果没有找到带有该vin的汽车,它将引发异常。
如果您想在发现多个错误时引发错误,那么您必须自己编写。如果您不应该遇到多辆汽车具有相同vin的情况,最好的方法是使用Car模型进行唯一性验证,例如
class Car < ActiveRecord::Base
validates_uniqueness_of :vin # or validates :vin, unique: true
end
您想要find_by_vin
(并且可以使用您的任何属性的名称替换vin
。
例如
Car.find_by_vin('123')
如果找不到带有该vin的汽车,或者具有该vin值的单辆汽车,则返回nil。如果你添加一个爆炸(即find_by_vin!
),如果没有找到带有该vin的汽车,它将引发异常。
有关详细信息:http://guides.rubyonrails.org/active_record_querying.html#retrieving-objects-from-the-database
答案 2 :(得分:1)
我认为没有任何东西可以抛出一个例外,但是在rails 4中只有一个:
car = Car.find_by(vin: '1234567890abcdefg')
将返回唯一的一个。强制唯一性的最佳方法是在模型/数据库级别上执行:
class Car < ActiveRecord::Base
validates :vin, uniqueness: true
end
如果由于某种原因,你确实需要在有多辆汽车的情况下抛出异常,你可以在模型上编写一个方法(或猴子补丁活动记录):
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")
答案 3 :(得分:0)
您可以使用take
和take!
car = Car.where(vin: '1234567890abcdefg').take
如果没有与给定字符串匹配的记录,则返回 nil 。
car = Car.where(vin: '1234567890abcdefg').take!
如果没有与给定字符串
匹配的记录,则返回ActiveRecord::RecordNotFound
来自Guides(1.1.2,1.1.5 and 1.1.6)
car = Car.take is equivalent to
SELECT * FROM cars LIMIT 1
答案 4 :(得分:0)
Rails 6.1 为此引入了 find_sole_by
(或 where(...).sole
)。
似乎完全符合要求:
<块引用>查找唯一匹配的记录。如果未找到记录,则引发 ActiveRecord::RecordNotFound
。如果找到多条记录,则引发 ActiveRecord::SoleRecordExceeded
。
用例很简单:
Car.find_sole_by(vin: '1234567890abcdefg')