5

ユーザーとネットワーク モデルの 1 対多の関連付けがあります。私のスキーマ情報の関連部分は次のとおりです。

# == Schema Information      
# Table name: users
#
#  id                     :integer         not null, primary key
#  name                   :string(255)

#
# Table name: networks
#
#  id         :integer         not null, primary key
#  user_id    :integer
#  uid        :string(255)
#  name   :string(255)
#  pub_url    :string(255)

ネットワーク モデルの name プロパティを使用して、特定の複数のネットワークを持つユーザーを除外したいと考えています。たとえば、facebook と foursquare をフィルターとしてチェックすると、facebook と foursquare の両方に接続しているユーザーを取得したいと考えています。私の現在の実装は、以下に示すように、ユーザーが追加できるネットワークの名前を含む配列を渡すことです。

filter :networks_name, :as => :check_boxes,
:collection => %w(facebook twitter foursquare linkedin)

ただし、これは、チェックされたアイテムのいずれかを持つユーザーを取得するフィルターに OR 条件を使用します。実際に取得したいのは、チェック項目をすべて満たすユーザーです。これを達成する正しい方法は何ですか?

4

1 に答える 1

4

ActiveAdmin はフィルターに meta_search を使用します ( https://github.com/ernie/meta_search ):

filter :networks_name_all,
  :as => :check_boxes,
  :collection => %w(facebook twitter foursquare linkedin)

そしてあなたのユーザーモデルでは:

scope :networks_names_all_in, -> names {
  names.reduce(scoped) do |scope, name|
    subquery = User.select('`users`.`id`').
      joins(:networks).
      where('networks.name = ?', name)
    scope.where("`users`.`id` IN (#{subquery.to_sql})")
  end
}
search_methods :networks_name_all_in

これにより、適切な結合と where 条件を使用して、適切な単一の SQL クエリが作成されます。

例えば:

User.networks_name_all_in(["facebook", "twitter"])

次の SQL リクエストが生成されます。

SELECT *
FROM `users`
WHERE `users`.`id` IN (SELECT `users`.`id`
                       FROM `users`
                       INNER JOIN `networks`
                       ON `networks`.`user_id` = `users`.`id`
                       WHERE `networks`.`name` = 'facebook')
  AND `users`.`id` IN (SELECT `users`.`id`
                       FROM `users`
                       INNER JOIN `networks`
                       ON `networks`.`user_id` = `users`.`id`
                       WHERE `networks`.`name` = 'twitter')

更新:機能範囲を追加しました。

更新 2:スコープのマージの問題に対してスコープを回復力のあるものにします。

于 2012-11-17T10:30:12.920 に答える