web-dev-qa-db-ja.com

Railsのコントローラーからレコードが存在するかどうかを確認します

私のアプリでは、ユーザーはビジネスを作成できます。 indexBusinessesControllerアクションをトリガーするとき、ビジネスがcurrent_user.idに関連しているかどうかを確認したい:

  • はいの場合:ビジネスを表示します。
  • いいえの場合:newアクションにリダイレクトします。

私はこれを使用しようとしていました:

if Business.where(:user_id => current_user.id) == nil
  # no business found
end

しかし、ビジネスが存在しない場合でも常にtrueを返します...

データベースにレコードが存在するかどうかをテストするにはどうすればよいですか?

77
user470763

コードが機能しないのはなぜですか?

whereメソッドは、ActiveRecord :: Relationオブジェクト(whereの結果を含む配列のように動作します)を返します。 空にすることはできますが、nilになることはありません。

Business.where(id: -1) 
 #=> returns an empty ActiveRecord::Relation ( similar to an array )
Business.where(id: -1).nil? # ( similar to == nil? )
 #=> returns false
Business.where(id: -1).empty? # test if the array is empty ( similar to .blank? )
 #=> returns true

少なくとも1つのレコードが存在するかどうかをテストするにはどうすればよいですか?

オプション1:.exists? の使用

if Business.exists?(user_id: current_user.id)
  # same as Business.where(user_id: current_user.id).exists?
  # ...
else
  # ...
end

オプション2:.present? を使用(または .blank?.present?の反対)

if Business.where(:user_id => current_user.id).present?
  # less efficiant than using .exists? (see generated SQL for .exists? vs .present?)
else
  # ...
end

オプション3:ifステートメントでの変数の割り当て

if business = Business.where(:user_id => current_user.id).first
  business.do_some_stuff
else
  # do something else
end

このオプションは、一部のリンター(Rubocopなど)によってコードのにおいと見なすことができます。

オプション3b:変数の割り当て

business = Business.where(user_id: current_user.id).first
if business
  # ...
else
  # ...
end

.find_by_user_id(current_user.id)の代わりに.where(...).firstを使用することもできます


最良のオプション:

  • Businessオブジェクトを使用しない場合:オプション1
  • Businessオブジェクトを使用する必要がある場合:オプション3
209
MrYoshiji

この場合、ActiveRecordが提供するexists?メソッドを使用します。

Business.exists? user_id: current_user.id
26
Hamed

「存在しますか?」

Business.exists? user_id: current_user.id #=> 1 or nil

「何か?」

Business.where(:user_id => current_user.id).any? #=> true or false

。whereで何かを使用する場合は、スコープの問題を回避し、より適切に使用してください 。unscoped

Business.unscoped.where(:user_id => current_user.id).any?
4
user2427993

ActiveRecord#whereは、ActiveRecord :: Relationオブジェクトを返します(nilになることはありません)。 .emptyを使用してみますか?リレーションでレコードを返すかどうかをテストします。

1
Puhlze

Business.where(:user_id => current_user.id)を呼び出すと、配列が取得されます。この配列にはオブジェクトがないか、1つまたは複数のオブジェクトが含まれている場合がありますが、nullにはなりません。したがって、check == nilは決して真になりません。

以下を試すことができます:

if Business.where(:user_id => current_user.id).count == 0

したがって、配列内の要素の数を確認し、それらをゼロと比較します。

またはあなたが試すことができます:

if Business.find_by_user_id(current_user.id).nil?

これは1またはnilを返します。

1
marimaf

オブジェクトのインスタンス変数を使用する必要がある場合は、このようにします。

if @business = Business.where(:user_id => current_user.id).first
  #Do stuff
else
  #Do stuff
end
0
user3633260
business = Business.where(:user_id => current_user.id).first
if business.nil?
# no business found
else
# business.ceo = "me"
end
0
Nino van Hooff