Rails3 Active Admin – 如何仅过滤满足集合中所有已检查项目的记录

我有一对多的用户与网络模型的关联。 我的架构信息的相关部分如下。

# == 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作为filter检查,我想找回连接facebook和foursquare的用户。 我目前的实现是传递一个数组,其中包含用户可以添加的网络名称,如下所示。

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

但是,这对filter使用OR条件,该filter检索具有任何已检查项目的用户。 我真正想要的是满足所有检查项目的用户。 实现这一目标的正确方法是什么?

ActiveAdmin将meta_search用于其filter( 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 

这将为您创建一个很好的单个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') 

更新:添加function范围。

更新2:使范围适应范围合并问题。