データベースがレコードを処理する前に返すかどうかを確認する最も効率的な方法は何ですか。例:Truck.where("id = ?", id).select('truck_no').first.truck_no
これは、トラックが存在する場合、トラックを返す場合と返さない場合があります。このリクエストを処理するときにページがクラッシュしないようにする最も効率的な方法は何ですか?ループを使用して各トラックを通過し、その番号を印刷するとしたら、ビューとコントローラーの両方でこれをどのように処理しますか?.
レコードが存在しない場合は、レコードが見つからないというメッセージを出力できるようにします。
オブジェクトの存在を確認したい場合、なぜuseが存在しないのですか?
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
#existsのRailsドキュメント? で他の例を見つけることができます。
これを確認する方法を次に示します。
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の実際のユースケースソリューション
最も簡単な解決策は、個別のDB呼び出しを行う代わりに、DBチェックとデータの取得を1つのDBクエリに結合することです。サンプルコードは近く、意図を伝えていますが、実際の構文では少しずれています。
単純にTruck.where("id = ?", id).select('truck_no').first.truck_no
を実行し、このレコードが存在しない場合、nil
はfirst
を取得する可能性があるため、_truck_no
_を呼び出すと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
_
自分がやろうとしていることを他の人が正確に把握できるように、それ自体を「コメント」するクリーンな構文を使用することをお勧めします。
本当にもう1マイル進んで行きたい場合は、これを実行して意図を伝える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?」を使用した一般的なソリューションmethod
他の貢献者の一部がすでに言及したように、_exists?
_メソッドは何かの存在をチェックするために特別に設計されています。値を返すのではなく、DBにいくつかの条件に一致するレコードがあることを確認するだけです。
あるデータの一意性または正確性を検証する必要がある場合に役立ちます。良い点は、ActiveRelation(Record?) where(...)
基準を使用できることです。
たとえば、User
属性を持つemail
モデルがあり、dBに電子メールが既に存在するかどうかを確認する必要がある場合:
User.exists?(email: "[email protected]")
_exists?
_を使用する利点は、SQLクエリの実行が
_SELECT 1 AS one FROM "users" WHERE "users"."email" = '[email protected]' LIMIT 1
_
実際にデータを返すよりも効率的です。
DBから実際に条件付きでデータを取得する必要がある場合、これは使用する方法ではありません。ただし、単純なチェックではうまく機能し、構文は非常に明確であるため、他の開発者はあなたが何をしているかを正確に知ることができます。複数の開発者がいるプロジェクトでは、適切な構文を使用することが重要です。クリーンなコードを記述し、コードにそれ自体を「コメント」させます。
あなたはただすることができます:
@truck_no = Truck.where("id = ?", id).pluck(:truck_no).first
レコードが見つからない場合はnil
を返し、_truck_no
of 最初のみレコード.
次に、あなたの意見では、次のようなことができます:
<%= @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? %>
レコードが存在するかどうかだけを確認したい場合。 @cristianの答え、つまり.
Truck.exists?(truck_id) # returns true or false
しかし、トラックが終了した場合、そのトラックにアクセスしたい場合は、2つのデータベースクエリにつながるトラックを再度見つける必要があります。これが事実である場合
@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