52

在处理之前检查数据库是否会返回记录的最有效方法是什么。例子:Truck.where("id = ?", id).select('truck_no').first.truck_no

如果卡车存在,这可能会或可能不会返回卡车。对我来说,确保在处理此请求时页面不会崩溃的最有效方法是什么。如果假设我使用循环遍历每辆卡车并打印出它的编号,我将如何在视图和控制器中处理这个问题。

如果记录不存在,我希望能够打印出一条消息,而不是说没有找到记录。

4

6 回答 6

110

如果要检查对象是否存在,为什么不使用存在?

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

您可以在Rails 文档中找到更多关于#exists? 的示例。.

于 2013-08-06T14:56:53.630 回答
35

这是您可以检查的方法。

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。

于 2013-08-06T14:24:20.593 回答
8

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_bywhere方法的顺序很重要;您必须selectTruck模型上调用。这是因为当您调用该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

这比实际返回数据更有效。

如果您实际上需要有条件地从数据库中检索数据,这不是要使用的方法。但是,它非常适合简单的检查,并且语法非常清晰,因此其他开发人员确切地知道您在做什么。在有多个开发人员的项目中,使用适当的语法至关重要。编写干净的代码,让代码自己“评论”。

于 2014-04-16T12:09:00.920 回答
3

如果您只想检查记录是否存在。选择@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
于 2019-05-23T03:45:33.900 回答
2

你可以这样做:

@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? %>
于 2013-08-06T14:24:23.270 回答
0

Rails 有一种persisted?随心所欲的使用方法

于 2016-03-19T16:03:16.707 回答