0

タイトルが紛らわしいのかもしれませんが、疑問をどう説明したらいいのかわかりませんでした。

Player というモデルをクエリするための連鎖を実行するために役立つ次のクラス メソッドがあるとします。プレイヤーはユーザーに属しますが、特定の村や都市からプレイヤーを取得したい場合は、ユーザー モデルを取得する必要があります。

def self.by_village(village)
  joins(:user).where(:village => "village")
end

def self.by_city(city)
  joins(:user).where(:city => "city")
end

村ごとだけでなく都市ごとにもプレイヤーをフェッチしたいとしましょう。

Player.by_city(city).by_village(village).

これはユーザーの結合を 2 回行うことになりますが、それは正しくないと思います..そうですか?

だから私の質問は次のとおりです。そうする正しい方法は何ですか?

4

1 に答える 1

0

私はそれを試していませんが、ActiveRecordが生成する実際のSQLクエリによってあなたの質問に対する答えを判断します。結合が1つだけの場合は、同じように使用します。これにより2つの結合が発生する場合は、by_village_and_cityメソッドを作成できます。

わかった。今それを試しました:

1.9.2p290 :022 > Player.by_city("Berlin").by_village("Kreuzberg")
  Player Load (0.3ms)  SELECT "players".* FROM "players" INNER JOIN "users" ON "users"."id" = "players"."user_id" WHERE "users"."city" = 'Berlin' AND "users"."village" = 'Kreuzberg'
 => [#<Player id: 1, user_id: 1, created_at: "2012-07-28 17:05:35", updated_at: "2012-07-28 17:05:35">, #<Player id: 2, user_id: 2, created_at: "2012-07-28 17:08:14", updated_at: "2012-07-28 17:08:14">] 

したがって、ActiveRecorsは2つのクエリを組み合わせて正しいことを行い、次の場合を除いてそれを使用します。ただし、実装を変更する必要がありました。

class Player < ActiveRecord::Base
  belongs_to :user
  def self.by_village(village)
    joins(:user).where('users.village' => village)
  end

  def self.by_city(city)
    joins(:user).where('users.city' => city)
  end
end

そして、あなたがしていることは通常、パラメータ化されたスコープで処理されます:

class Player < ActiveRecord::Base
  belongs_to :user

  scope :by_village, lambda { |village| joins(:user).where('users.village = ?', village) }
  scope :by_city, lambda { |city| joins(:user).where('users.city = ?', city) }

end
于 2012-07-28T17:01:37.013 に答える