Rails检查数据库中是否存在记录

Boj*_*jan 46 database null ruby-on-rails

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

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

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

cri*_*ian 97

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

if Truck.exists?(10)
  # your truck exists in the database
else
  # the truck doesn't exist
end
Run Code Online (Sandbox Code Playgroud)

exists?方法的优点是不从数据库中选择记录(意味着比选择记录更快).查询看起来像:

SELECT 1 FROM trucks where trucks.id = 10
Run Code Online (Sandbox Code Playgroud)

您可以在http://api.rubyonrails.org/classes/ActiveRecord/FinderMethods.html#method-i-exists-3F找到更多示例.

  • “存在”不仅限于对象的主键。您也可以通过这样的查询:`Person.exists?([['name LIKE?',“%#{query}%”]])` (2认同)

Sha*_*nak 35

这是你如何检查这个.

if Trucks.where(:id => current_truck.id).blank?
  # no truck record for this id
else
  # at least 1 record for this truck
end
Run Code Online (Sandbox Code Playgroud)

where方法返回一个ActiveRecord :: Relation对象(就像一个包含where的结果的数组),它可以是空的但永远不会是nil.

  • 使用`exists?`插入`blank?`.这将执行查询以检查DB中是否存在对象,而不是检索整个对象. (6认同)
  • @ImranNaqvi使用“空白”会更糟,因为它会在检查是否存在“存在”之前返回_all_记录,并将LIMIT 1添加到sql语句中,这样最多只能加载一条记录。请参阅下面的@cristian答案。 (2认同)

Dan*_*n L 8

OP实际用例解决方案

最简单的解决方案是将数据库检查和数据检索组合到1个DB查询中,而不是单独的数据库调用.您的示例代码很接近并传达了您的意图,但实际语法中有点偏差.

如果您这么简单,Truck.where("id = ?", id).select('truck_no').first.truck_no并且此记录不存在,则nil在您调用时会抛出错误,truck_no因为如果找不到符合您条件firstnil记录,则可能会检索记录.

那是因为您的查询将返回符合您条件的对象数组,然后您first在该数组上执行(如果找不到匹配的记录)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
Run Code Online (Sandbox Code Playgroud)

我建议使用"注释"本身的干净语法,以便其他人确切地知道您正在尝试做什么.

如果你真的想加倍努力,你可以为你的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
Run Code Online (Sandbox Code Playgroud)

然后你会这样称呼它:

if truck_number = Truck.truck_number_if_exists(id)
  # do processing because record exists and you have the value
else
  # no matching criteria
end
Run Code Online (Sandbox Code Playgroud)

ActiveRecord.find_by方法将检索与您的条件匹配的第一条记录,否则nil如果未找到具有该条件的记录则返回.请注意,find_bywhere方法的顺序很重要; 你必须打电话selectTruck模特.这是因为当你调用where方法时,你实际上正在返回一个ActiveRelation不是你想要的对象.

有关'find_by'方法,请参阅ActiveRecord API

使用'存在?'的一般解决方案 方法

正如其他一些贡献者已经提到的那样,该exists?方法专门用于检查某些东西的存在.它不返回值,只是确认DB具有符合某些条件的记录.

如果您需要验证某些数据的唯一性或准确性,这将非常有用.好的部分是它允许您使用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

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

如果您需要实际有条件地从数据库中检索数据,则这不是要使用的方法.但是,它非常适合简单检查,语法非常清晰,因此其他开发人员确切知道您正在做什么.在具有多个开发人员的项目中,使用适当的语 编写干净的代码,让代码"注释"自己.

  • 这是一个非常有用的演练,谢谢 (2认同)