1. ホーム
  2. ruby-on-rails

Rails ActiveRecordは、複数のクエリを使用せずに、どのように「where」句を連鎖させるのですか?

2023-07-26 23:10:39

質問

私はRuby on Railsの素晴らしさを学んでいるPHP開発者です。私はActiveRecordが大好きで、とても興味深いことに気づきました。それは、ActiveRecordのメソッドが、クエリを実行するためにメソッドチェーンの終わりを検出する方法です。

@person = Person.where(name: 'Jason').where(age: 26)

# In my humble imagination I'd think that each where() executes a database query
# But in reality, it doesn't until the last method in the chain

この魔術はどのように働くのですか?

どのように解決するのですか?

この where メソッドは ActiveRecord::Relation オブジェクトを返し、それ自身はデータベースクエリを発行しません。それは ここで であり、このオブジェクトを使用することが重要なのです。

コンソールでは、おそらくこうなっているはずです。

@person = Person.where(name: "Jason")

そして blammo を実行すると、データベースクエリが発行され、Jasonという名前の全員の配列のようなものが返されます。やったね、Active Record!

しかし、次にこのようなことをします。

@person = Person.where(name: "Jason").where(age: 26)

そしてまた別のクエリを発行します。これは26歳のJasonと呼ばれる人たちに対するものです。 しかし、発行されるのは 1 クエリしか発行しないので、他のクエリはどこに行ったのでしょうか?


他の方が示唆されているように、この現象は where メソッドはプロキシオブジェクトを返します。実際にクエリを実行し、データセットを返すことは、それを要求されない限りありません。

を実行するとき 何でも を実行すると、実行した結果のインスパイア版が出力されます。もしあなたが 1 と入力し、Enterキーを押すと 1 と表示されます。 1.inspect1 . マジック!同じことが "1" . 他のさまざまなオブジェクトには inspect メソッドが定義されていないため、Ruby は Object を返す おぞましい のように <Object#23adbf42560> .

いちいち ActiveRecord::Relation オブジェクトは inspect メソッドが定義されているので、クエリが発生します。コンソールでクエリを書くと、IRB は inspect を呼び出し、ほとんど人間が読めるようなもの、つまりあなたが見ているようなArrayを出力します。


標準的な Ruby スクリプトでこれを発行していた場合、オブジェクトが検査されるまでクエリは実行されません ( inspect を使って) 検査されるか、あるいは each を使うか、あるいは to_a メソッドが呼び出されます。

これら三つのうち一つでも起こるまでは、いくつでもチェーンして where ステートメントを好きなだけ連鎖させることができ、その後に する を呼び出します。 inspect , to_a または each を付けると、最終的にそのクエリを実行します。