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

时间:2013-08-06 14:18:43

标签: ruby-on-rails database null

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

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

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

6 个答案:

答案 0 :(得分:92)

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

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 documentation for #exists?中找到更多示例。

答案 1 :(得分:35)

以下是检查方法。

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

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

答案 2 :(得分:8)

OP实际用例解决方案

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

如果您执行Truck.where("id = ?", id).select('truck_no').first.truck_no并且此记录不存在,则在您致电nil时会出现truck_no错误,因为first可能会检索nil如果找不到符合您条件的记录,则记录。

这是因为您的查询将返回符合条件的对象数组,然后您对该数组执行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

我建议使用干净的语法&#34; comments&#34;本身让其他人确切地知道你正在尝试做什么。

如果您真的想加倍努力,可以在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方法的顺序很重要;您必须致电select模型上的Truck。这是因为当您调用where方法时,您实际上会返回ActiveRelation对象,而这不是您在此处寻找的对象。

See ActiveRecord API for 'find_by' method

使用&#39;的常规解决方案?&#39;方法

正如其他一些贡献者已经提到的那样,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

比实际返回数据更有效。

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

答案 3 :(得分:2)

你可以这样做:

@truck_no = Truck.where("id = ?", id).pluck(:truck_no).first

如果未找到任何记录,则会返回nil,否则将返回仅{/ 1>} 记录。

然后在你的视图中你可以做类似的事情:

truck_no

如果要获取并显示多个结果,请在控制器中:

<%= @truck_no || "There are no truck numbers" %>

并在您看来:

@truck_nos = Truck.where("id = ?", id).pluck(:truck_no)

答案 4 :(得分:0)

如果只想检查记录是否存在。与@cristian的答案一起使用,即

Truck.exists?(truck_id) # returns true or false

但是,如果卡车驶出,那么您想访问该卡车,则必须再次找到卡车,这将导致两个数据库查询。如果是这种情况,请

@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

答案 5 :(得分:-1)

Rails有persisted?方法  像你想要的那样使用