3

この ruby​​/rails 構造は、いつも私を困惑させます:

User.where(:name => "Thiago").limit(3).using(:slave_one)

これは左から右に実行する必要があるため、連続する呼び出しごとにレシーバーが設定されます。whereのインスタンスを返すUser クラスから始めますActiveRecord::Relation。次にlimit、そのインスタンスで が呼び出され、 の別のインスタンスが返されますActiveRecord::Relation。次にusing、そのインスタンスで呼び出されます (たまたまシャードが選択されます)。全体がオブジェクト内に SQL クエリを構築しているActiveRecord::Relationと思います。私の質問は、「何がクエリの実際の実行をトリガーするのか」ということです。クエリをさらに変更する後続処理がチェーン内に存在する可能性があるため、チェーン内の特定の時点で実行することはできません。そのあともusing追加のメソッドがチェーンに追加されているかどうかがわからないため、クエリはまだ実行できません。明らかに、構築後にクエリを実行しますが、クエリは実際にどのように呼び出されるのでしょうか?


ありがとう...チェーン内のメソッドの名前には「セマンティクス」があることがわかりました。作成中のクエリをさらに変更する人もいます。最後の 1 つだけが、データのフェッチが必要なタイプである可能性があります。

4

2 に答える 2

7

ActiveRecord::Relation は、データを要求するまでデータベースと対話する必要はありません。例えば:

User.where(:name => "Thiago").limit(3).using(:slave_one).count
# talks to the database here ----------------------------^^^^^

ActiveRecord::Relation を見ると、ActiveRecord::QueryMethodsが含まれていることがわかります。そこにあるほとんどのものは次のようになっています。

def x(*args)
  relation = clone
  # merge args into relation
  relation
end

したがって、リレーションは、クエリの実行が必要な何かを行うまで、クエリを少しずつ構築します。次に、適切な SQL を構築し、それをデータベースに送り、データベースが送り返すものに対して (理論的には) 何か役に立つことを行います。

また、各 QueryMethods メソッドは、クローン化および変更されたリレーションを返すため、次のようなことができることに注意してください。

r1 = User.where(:name => 'Pancakes')
r2 = r1.limit(3)

を使用r1して、すべての一致を取得するかr2、3 つだけを取得します。

于 2011-08-30T18:51:48.710 に答える
3

この構造 (構築中にクエリが実行されない) は意図的なものです。それは遅延読み込みと呼ばれます。

クエリは、リレーションからのデータを最初に要求したときに実行されます。あなたが持っていた場合のIE:

@users = User.where(:name => "Thiago").limit(3).using(:slave_one)
@users.first.name #the query executes here

通常、これはクエリからデータを呼び出すビュー テンプレートの最初の行のときに実行されます。

于 2011-08-30T18:51:50.603 に答える