Ruby-on-rails Rails 检查数据库中是否存在记录
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18082778/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Rails checking if a record exists in database
提问by Bojan
What is the most efficient of way of checking if a database will return a record before processing it. Example: Truck.where("id = ?", id).select('truck_no').first.truck_no
在处理之前检查数据库是否会返回记录的最有效方法是什么。例子:Truck.where("id = ?", id).select('truck_no').first.truck_no
This may or may not return a truck if the truck exists. What is the most efficient way for me to ensure the page will not crash when processing this request. How would I handle this both in the view and the controller if lets say I was using a loop to go through each truck and print out its number.
如果卡车存在,这可能会也可能不会返回卡车。对我来说,确保在处理此请求时页面不会崩溃的最有效方法是什么。如果假设我使用循环遍历每辆卡车并打印出其编号,我将如何在视图和控制器中处理此问题。
If the record does not exist I would like to be able to print out a message instead saying no records found.
如果记录不存在,我希望能够打印出一条消息,而不是说没有找到记录。
回答by cristian
If you want to check for the existence of an object why not use exists?
如果要检查对象是否存在,为什么不使用exists?
if Truck.exists?(10)
# your truck exists in the database
else
# the truck doesn't exist
end
The exists?method has the advantage that is not selecting the record from the database (meaning is faster than selecting the record).
The query looks like:
该exists?方法的优点是不从数据库中选择记录(意思是比选择记录更快)。查询如下所示:
SELECT 1 FROM trucks where trucks.id = 10
You can find more examples in the Rails documentation for #exists?.
回答by Shaunak
Here is how you can check this.
这是您可以检查的方法。
if Trucks.where(:id => current_truck.id).blank?
# no truck record for this id
else
# at least 1 record for this truck
end
wheremethod returns an ActiveRecord::Relation object(acts like an array which contains the results of the where), it can be empty but never be nil.
where方法返回一个ActiveRecord::Relation 对象(就像一个包含 where 结果的数组),它可以为空,但永远不会为 nil。
回答by Dan L
OP actual use case solution
OP实际用例解决方案
The simplest solution is to combine your DB check and retrieval of data into 1 DB query instead of having separate DB calls. Your sample code is close and conveys your intent, but it's a little off in your actual syntax.
最简单的解决方案是将您的 DB 检查和数据检索合并到 1 个 DB 查询中,而不是进行单独的 DB 调用。您的示例代码很接近并传达了您的意图,但在您的实际语法中有点偏离。
If you simple do Truck.where("id = ?", id).select('truck_no').first.truck_noand this record does NOT exists, it will throw a nilerror when you call truck_nobecause firstmay retrieve a nilrecord if none are found that match your criteria.
如果您简单地执行Truck.where("id = ?", id).select('truck_no').first.truck_no并且此记录不存在,则nil在您调用时它会抛出错误,truck_no因为如果找不到与您的条件匹配first的nil记录,则可能会检索记录。
That's because your query will return an array of objects that match your criteria, then you do a firston that array which (if no matching records are found) is nil.
那是因为您的查询将返回一个与您的条件匹配的对象数组,然后您first对该数组执行 a (如果没有找到匹配的记录)是nil.
A fairly clean solution:
一个相当干净的解决方案:
# 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
I recommend using clean syntax that "comments" itself so others know exactly what you're trying to do.
我建议使用“评论”本身的干净语法,以便其他人确切地知道您要做什么。
If you really want to go the extra mile, you could add a method to your Truckclass that does this for you and conveys your intent:
如果你真的想加倍努力,你可以在你的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
Then you would call it like so:
然后你会这样称呼它:
if truck_number = Truck.truck_number_if_exists(id)
# do processing because record exists and you have the value
else
# no matching criteria
end
The ActiveRecord.find_bymethod will retrieve the first record that matches your criteria or else returns nilif no record is found with that criteria. Note that the order of the find_byand wheremethods is important; you must call the selecton the Truckmodel. This is because when you call the wheremethod you're actually returning an ActiveRelationobject which is not what you're looking for here.
该ActiveRecord.find_by方法将检索与您的条件匹配的第一条记录,否则nil如果没有找到符合该条件的记录,则返回。注意find_by和where方法的顺序很重要;您必须调用模型select上的Truck。这是因为当您调用该where方法时,您实际上返回的ActiveRelation是一个不是您在此处寻找的对象。
See ActiveRecord API for 'find_by' method
'find_by' 方法见 ActiveRecord API
General solutions using 'exists?' method
使用“存在吗?”的通用解决方案 方法
As some of the other contributors have already mentioned, the exists?method is engineered specifically to check for the existence of something. It doesn't return the value, just confirms that the DB has a record that matches some criteria.
正如其他一些贡献者已经提到的那样,该exists?方法专门设计用于检查某些东西的存在。它不返回值,只是确认数据库具有符合某些条件的记录。
It is useful if you need to verify uniqueness or accuracy of some piece of data. The nice part is that it allows you to use the ActiveRelation(Record?) where(...)criteria.
如果您需要验证某些数据的唯一性或准确性,它会很有用。好的部分是它允许您使用ActiveRelation(Record?) where(...)标准。
For instance, if you have a Usermodel with an emailattribute and you need to check if an email already exists in the dB:
例如,如果您有一个User具有email属性的模型,并且您需要检查 dB 中是否已存在电子邮件:
User.exists?(email: "[email protected]")
User.exists?(email: "[email protected]")
The benefit of using exists?is that the SQL query run is
使用的好处exists?是 SQL 查询运行是
SELECT 1 AS one FROM "users" WHERE "users"."email" = '[email protected]' LIMIT 1
SELECT 1 AS one FROM "users" WHERE "users"."email" = '[email protected]' LIMIT 1
which is more efficient than actually returning data.
这比实际返回数据更有效。
If you need to actually conditionally retrieve data from the DB this isn't the method to use. However, it works great for simple checking and the syntax is very clear so other developers know exactly what you're doing. Using appropriate syntax is critical in projects with multiple developers. Write clean code and let the code "comment" itself.
如果您需要实际有条件地从数据库中检索数据,这不是要使用的方法。但是,它非常适合简单的检查,并且语法非常清晰,因此其他开发人员可以确切地知道您在做什么。在有多个开发人员的项目中,使用适当的语法至关重要。编写干净的代码并让代码“评论”自己。
回答by Agis
You could just do:
你可以这样做:
@truck_no = Truck.where("id = ?", id).pluck(:truck_no).first
This will return nilif no record is found, or truck_noof only the firstrecord otherwise.
这将返回nil如果没有找到记录,或truck_no中只有第一个,否则记录。
Then in your view you could just do something like:
然后在您看来,您可以执行以下操作:
<%= @truck_no || "There are no truck numbers" %>
If you want to fetch and display multiple results, then in your controller:
如果要获取并显示多个结果,请在控制器中:
@truck_nos = Truck.where("id = ?", id).pluck(:truck_no)
and in your view:
在您看来:
<% truck_nos.each do |truck_no| %>
<%= truck_no %>
<% end %>
<%= "No truck numbers to iterate" if truck_nos.blank? %>
回答by Imran Ahmad
If you just want to check whether the record exists or not. Go with the @cristian's answer i.e.
如果您只想检查记录是否存在。使用@cristian 的答案,即
Truck.exists?(truck_id) # returns true or false
Truck.exists?(truck_id) # returns true or false
But if truck exits then you want to access that truck then you will have to find truck again which will lead to two database query. If this is the case go with
但是如果卡车退出,那么你想要访问那辆卡车,那么你将不得不再次找到卡车,这将导致两个数据库查询。如果是这种情况,请使用
@trcuk = Truck.find_by(id: truck_id) #returns nil or truck
@truck.nil? #returns true if no truck is db
@truck.present? #returns true if no truck is db
回答by user1810122
Rails has a persisted?method
for using like you want
Rails 有一种persisted?可以随心所欲使用的方法

