正しい機会に使用していることを確認し、微妙な点を知りたいです。それらは同じように機能しているように見えます。つまり、コンソールを介してそれらを使用し、グーグル検索を行ったときにオンラインで多くの情報がない場合、オブジェクトフィールドが定義されているかどうかを確認します。ありがとう!
6 に答える
明確にするために:「純粋な」ルビーでも、どちらpresent?
もexists?
Rails-landからのものではありません。
現在?
present?
のActiveSupport拡張機能Object
です。これは通常、オブジェクトの一般的な「偽り」のテストとして使用されます。ドキュメントから:
オブジェクトは
present
、そうでない場合blank?
です。オブジェクトはblank
、それがfalse
、空、または空白文字列の場合です。
したがって、たとえば:
[ "", " ", false, nil, [], {} ].any?(&:present?)
# => false
存在しますか?
exists?
ActiveResourceからです。そのドキュメントから:
リソースの存在をアサートし、リソースが見つかった場合はtrueを返します。
Note.create(:title => 'Hello, world.', :body => 'Nothing more for now...')
Note.exists?(1) # => true
2つのメソッドの大きな違いは、呼び出すpresent?
と、見つかったレコードごとにActiveRecordが初期化される(!)が、そうでexists?
はないことです。
これを示すために、Userにafter_initializeを追加しました。次のように出力されます。'オブジェクトを初期化しました!'
User.where(name:'mike')。present?
User Load (8.1ms) SELECT "users".* FROM "users" WHERE "users"."name" = $1 ORDER BY users.id ASC [["name", 'mike']]
You have initialized an object!
You have initialized an object!
User.exists?(名前:'マイク')
User Exists (2.4ms) SELECT 1 AS one FROM "users" WHERE "users"."name" = $1 ORDER BY users.id ASC LIMIT 1 [["name", 'mike']]
パフォーマンスには大きな違いがあり、チェックしている関係によっては、.present?
最大10倍遅くなる可能性があります。.exists?
この記事.present?
では、 vs .any?
vsのベンチマーク.exists?
を行い、なぜそれらが遅いものから速いものへとこの順序で進むのかを説明します。
一言で言えば、.present?
(例では900ms)は返されたすべてのレコードをロードし、.any?
(例では100ms)はSQLCountを使用してそれが0より大きいかどうかを確認し、.exists?
(例では1ms)はSQLLIMIT1を使用する賢い子供ですすべてをロードせずに、すべてをカウントせずに、少なくとも1つのレコードがあるかどうかを確認します。
SELECT COUNT(*)
レコードをスキャンしてカウントを取得します。
SELECT 1
最初の試合の後に停止するので、彼らの実行時間は非常に異なります。
2つによって生成されるSQLも異なります。
present?
:
Thing.where(name: "Bob").present?
# => SELECT COUNT(*) FROM things WHERE things.name = "Bob";
exists?
:
Thing.exists?(name: "Bob")
# => SELECT 1 AS one from things WHERE name ="Bob" limit 1;
どちらも同じ速度で動作しているように見えますが、状況によって異なる場合があります。
以下を使用して、データベースクエリを回避できますpresent?
。
all_endorsements_11 = ArtworkEndorsement.where(user_id: 11)
ArtworkEndorsement Load (0.3ms) SELECT "artwork_endorsements".* FROM "artwork_endorsements" WHERE "artwork_endorsements"."user_id" = $1 [["user_id", 11]]
all_endorsements_11.present?
=> true
all_endorsements_11.exists?
ArtworkEndorsement Exists (0.4ms) SELECT 1 AS one FROM "artwork_endorsements" WHERE "artwork_endorsements"."user_id" = $1 LIMIT 1 [["user_id", 11]]
=> true