dan*_*eta 5 ruby-on-rails activeadmin
我有一对多的用户与网络模型的关联.我的架构信息的相关部分如下.
# == 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)
Run Code Online (Sandbox Code Playgroud)
我想使用网络模型的name属性过滤掉具有特定多个网络的用户.例如,如果我将facebook和foursquare作为过滤器检查,我想找回连接facebook和foursquare的用户.我目前的实现是传递一个数组,其中包含用户可以添加的网络名称,如下所示.
filter :networks_name, :as => :check_boxes,
:collection => %w(facebook twitter foursquare linkedin)
Run Code Online (Sandbox Code Playgroud)
但是,这对过滤器使用OR条件,该过滤器检索具有任何已检查项的用户.我真正想要的是满足所有检查项目的用户.实现这一目标的正确方法是什么?
ActiveAdmin 使用 meta_search 作为过滤器(https://github.com/ernie/meta_search):
filter :networks_name_all,
:as => :check_boxes,
:collection => %w(facebook twitter foursquare linkedin)
Run Code Online (Sandbox Code Playgroud)
在您的用户模型中:
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
Run Code Online (Sandbox Code Playgroud)
这将为您创建一个很好的单个 SQL 查询,并具有适当的联接和 where 条件。
例如:
User.networks_name_all_in(["facebook", "twitter"])
Run Code Online (Sandbox Code Playgroud)
将生成以下 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')
Run Code Online (Sandbox Code Playgroud)
更新:添加了功能范围。
更新 2:使范围能够适应范围合并问题。
| 归档时间: |
|
| 查看次数: |
1902 次 |
| 最近记录: |