在处理之前检查数据库是否会返回记录的最有效方法是什么。例子:Truck.where("id = ?", id).select('truck_no').first.truck_no
如果卡车存在,这可能会或可能不会返回卡车。对我来说,确保在处理此请求时页面不会崩溃的最有效方法是什么。如果假设我使用循环遍历每辆卡车并打印出它的编号,我将如何在视图和控制器中处理这个问题。
如果记录不存在,我希望能够打印出一条消息,而不是说没有找到记录。
在处理之前检查数据库是否会返回记录的最有效方法是什么。例子:Truck.where("id = ?", id).select('truck_no').first.truck_no
如果卡车存在,这可能会或可能不会返回卡车。对我来说,确保在处理此请求时页面不会崩溃的最有效方法是什么。如果假设我使用循环遍历每辆卡车并打印出它的编号,我将如何在视图和控制器中处理这个问题。
如果记录不存在,我希望能够打印出一条消息,而不是说没有找到记录。
如果要检查对象是否存在,为什么不使用存在?
if Truck.exists?(10)
# your truck exists in the database
else
# the truck doesn't exist
end
该exists?
方法的优点是不从数据库中选择记录(意思是比选择记录更快)。查询如下所示:
SELECT 1 FROM trucks where trucks.id = 10
这是您可以检查的方法。
if Trucks.where(:id => current_truck.id).blank?
# no truck record for this id
else
# at least 1 record for this truck
end
where方法返回一个ActiveRecord::Relation 对象(就像一个包含 where 结果的数组),它可以是空的,但永远不会是 nil。
OP实际用例解决方案
最简单的解决方案是将您的数据库检查和数据检索合并到 1 个数据库查询中,而不是使用单独的数据库调用。您的示例代码很接近并传达了您的意图,但在您的实际语法中有点偏离。
如果你简单地做Truck.where("id = ?", id).select('truck_no').first.truck_no
并且这条记录不存在,nil
当你调用它时会抛出一个错误,truck_no
因为如果没有找到符合你的条件的记录,它first
可能会检索到一条记录。nil
那是因为您的查询将返回一个与您的条件匹配的对象数组,然后您first
对该数组执行 a (如果没有找到匹配的记录)是nil
.
一个相当干净的解决方案:
# Note: using Rails 4 / Ruby 2 syntax
first_truck = Truck.select(:truck_no).find_by(id) # => <Truck id: nil, truck_no: "123"> OR nil if no record matches criteria
if first_truck
truck_number = first_truck.truck_no
# do some processing...
else
# record does not exist with that criteria
end
我建议使用“注释”本身的简洁语法,以便其他人确切知道您要做什么。
如果你真的想加倍努力,你可以在你的Truck
类中添加一个方法来为你做这件事并传达你的意图:
# truck.rb model
class Truck < ActiveRecord::Base
def self.truck_number_if_exists(record_id)
record = Truck.select(:truck_no).find_by(record_id)
if record
record.truck_no
else
nil # explicit nil so other developers know exactly what's going on
end
end
end
然后你会这样称呼它:
if truck_number = Truck.truck_number_if_exists(id)
# do processing because record exists and you have the value
else
# no matching criteria
end
该ActiveRecord.find_by
方法将检索与您的条件匹配的第一条记录,或者nil
如果没有找到符合该条件的记录,则返回。注意find_by
和where
方法的顺序很重要;您必须select
在Truck
模型上调用。这是因为当您调用该where
方法时,您实际上返回的ActiveRelation
对象不是您在此处寻找的对象。
'find_by' 方法见 ActiveRecord API
使用“存在?”的一般解决方案 方法
正如其他一些贡献者已经提到的那样,该exists?
方法专门设计用于检查某物的存在。它不返回值,只是确认数据库有符合某些条件的记录。
如果您需要验证某些数据的唯一性或准确性,它会很有用。好的部分是它允许您使用ActiveRelation(Record?) where(...)
标准。
例如,如果您有一个User
带有email
属性的模型,并且您需要检查一个电子邮件是否已经存在于 dB 中:
User.exists?(email: "test@test.com")
使用的好处exists?
是SQL查询运行是
SELECT 1 AS one FROM "users" WHERE "users"."email" = 'test@test.com' LIMIT 1
这比实际返回数据更有效。
如果您实际上需要有条件地从数据库中检索数据,这不是要使用的方法。但是,它非常适合简单的检查,并且语法非常清晰,因此其他开发人员确切地知道您在做什么。在有多个开发人员的项目中,使用适当的语法至关重要。编写干净的代码,让代码自己“评论”。
如果您只想检查记录是否存在。选择@cristian的答案,即
Truck.exists?(truck_id) # returns true or false
但是如果卡车存在并且您想访问该卡车,那么您将不得不再次找到卡车,这将导致两个数据库查询。如果是这种情况,请使用
@truck = Truck.find_by(id: truck_id) #returns nil or truck
@truck.nil? #returns true if no truck in db
@truck.present? #returns true if no truck in db
你可以这样做:
@truck_no = Truck.where("id = ?", id).pluck(:truck_no).first
nil
如果没有找到记录,这将返回truck_no
,否则只有第一条记录。
然后在您看来,您可以执行以下操作:
<%= @truck_no || "There are no truck numbers" %>
如果你想获取并显示多个结果,那么在你的控制器中:
@truck_nos = Truck.where("id = ?", id).pluck(:truck_no)
在您看来:
<% truck_nos.each do |truck_no| %>
<%= truck_no %>
<% end %>
<%= "No truck numbers to iterate" if truck_nos.blank? %>
Rails 有一种persisted?
随心所欲的使用方法