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


91

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

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

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

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

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

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


1
whereレコードがない場合、を使用すると空の配列が返されます。そして[]等しくないnil
mind.blank 2013年

ただはunless Business.find_by_user_id(current_user.id)どうですか?
Hengjie 2013年

回答:


231

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

このwhereメソッドはActiveRecord :: Relationshipオブジェクト(の結果を含む配列のように機能します)を返します。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

それはうまくいかなかったようです。== nilテストのように、そのテストに合格し、インデックスhtmlをロードし続けます(エラーが発生します:nil:NilClassの未定義のメソッド `name ')。

現在を呼び出す前に最初に試してみてください
MrYoshiji 2013年

同じ問題が発生します

ああ、それは私が混乱していた私のせいです、あなたはテストする必要がありますblank?
MrYoshiji 2013年

うまくいったありがとう!私はその間違いに気付くべきではなかった。== nilチェックが機能しなかった理由を教えてください。

29

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

Business.exists? user_id: current_user.id

存在しますか?または可能ですか?
イムランアフマド

5

「存在しますか?」:

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

'any?':

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

.whereで何かを使用する場合は、スコープの問題を回避し、.unscopedを使用することをお勧めします

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

Business.unscoped.where(:user_id => current_user.id).pluck(:id).any?を使用することをお勧めします。チェックしているオブジェクトの関係の不必要な負荷を避けるため。
Juanin 2016

1

ActiveRecord#whereは、ActiveRecord :: Relationshipオブジェクトを返します(これは決してnilにはなりません)。.emptyを使用してみますか?それがレコードを返すかどうかをテストするための関係について。


1

呼び出す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を返します。



0

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

if @business = Business.where(:user_id => current_user.id).first
  #Do stuff
else
  #Do stuff
end
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.