Activeadmin:如何过滤匹配两个或多个搜索词的字符串
Activeadmin: how to filter for strings that match two or more search terms
假设我的用户 class 有一个 :email 字段。假设我正在使用 activeadmin 来管理用户。
制作一个过滤器 returns 匹配一个字符串的电子邮件,例如"smith",很简单。在 admin/user.rb
中,我只包含行
filter :email
这给了我一个过滤器小部件来完成这项工作。
但是,此过滤器不允许我搜索多个术语的交集。我可以搜索包含 "smith" 的电子邮件,但不能搜索同时包含 "smith" 和“.edu”的电子邮件。
Google 告诉我 activerecord 使用 Ransack under the hood, and the Ransack demo 有一个 'advanced' 模式允许多个词搜索。
将多词搜索小部件放入 activeadmin 的最简单方法是什么?
理想情况下,我想要一个允许我输入 smith .edu
或 smith AND .edu
以过滤包含这两个术语的电子邮件的小部件。
只需向您的模型添加三个过滤器:
filter :email_cont
filter :email_start
filter :email_end
它为您提供了一种灵活的方式来管理您的搜索。
此过滤器执行下一个 sql 代码:
SELECT "admin_users".* FROM "admin_users"
WHERE ("admin_users"."email" ILIKE '%smith%' AND
"admin_users"."email" ILIKE '%\.edu')
ORDER BY "admin_users"."id" desc LIMIT 30 OFFSET 0
我希望这正是您要找的。
我找到了一个解决方案,但它并不完美。
好消息是 Ransack 可以轻松进行多词搜索。这些搜索使用 'predicate' cont_all
。以下行用于查找包含 'smith' 和 '.edu'.
的电子邮件
User.ransack(email_cont_all: ['smith','.edu'] ).result
由于这些搜索在 Ransack 中很容易,因此在 Activeadmin 中可能也很简单,对吧?错误的!为了让它们正常工作,我需要做三件事。
我把一个自定义的搜索方法(a.k.a。ransacker)放到了User.rb
。我将劫掠者命名为 email_multiple_terms
。
class User < ActiveRecord::Base
# ...
ransacker :email_multiple_terms do |parent|
parent.table[:path]
end
我在我的 activeadmin 仪表板中声明了一个过滤器,并将其与劫掠者相关联。请注意,搜索谓词 cont_all
附加到劫掠者名称。
admin/User.rb
:
ActiveAdmin.register User do
# ...
filter :email_multiple_terms_cont_all, label: "Email", as: :string
此行在 Activeadmin 中创建过滤器小部件。我们快到了。剩下的一个问题:Activeadmin 将搜索查询作为单个字符串(例如 "smith .edu"
)发送给搜查,而我们的搜查者希望将搜索词作为一个数组。在某处,我们需要将单个字符串转换为搜索词数组。
我修改了 activeadmin 以在特定条件下拆分搜索字符串。逻辑在我添加到 lib/active_admin/resource_controller/data_access.rb.
的方法中
def split_search_params(params)
params.keys.each do |key|
if key.ends_with? "_any" or key.ends_with? "_all"
params[key] = params[key].split # turn into array
end
end
params
end
然后我在apply_filtering
里面调用了这个方法。
def apply_filtering(chain)
@search = chain.ransack split_search_params clean_search_params params[:q]
@search.result
end
此代码存在于我自己的 activeadmin 分支中,此处:https://github.com/d-H-/activeadmin
因此,要进行多词搜索,请按照上面的步骤 1 和 2 进行操作,并包括我的 A.A 分支。在你的 Gemfile 中:
gem 'activeadmin', :git => 'git://github.com/d-H-/activeadmin.git'
HTH.
如果谁有更简单的方法,请分享!
有一个使用 ranasckable 范围的简单解决方案
所以在你的模型中加入这样的东西
class User < ActiveRecord::Base
....
scope :email_includes, ->(search) {
current_scope = self
search.split.uniq.each do |word|
current_scope = current_scope.where('user.email ILIKE ?', "%#{word}%")
end
current_scope
}
def self.ransackable_scopes(auth_object = nil)
[ :email_includes]
end
end
之后您可以使用 AA DSL 添加过滤器
喜欢
filter :email_includes, as: :string, label: "Email"
UPD
如果将 email_contains_any
更改为 email_includes
应该可以工作
假设我的用户 class 有一个 :email 字段。假设我正在使用 activeadmin 来管理用户。
制作一个过滤器 returns 匹配一个字符串的电子邮件,例如"smith",很简单。在 admin/user.rb
中,我只包含行
filter :email
这给了我一个过滤器小部件来完成这项工作。
但是,此过滤器不允许我搜索多个术语的交集。我可以搜索包含 "smith" 的电子邮件,但不能搜索同时包含 "smith" 和“.edu”的电子邮件。
Google 告诉我 activerecord 使用 Ransack under the hood, and the Ransack demo 有一个 'advanced' 模式允许多个词搜索。
将多词搜索小部件放入 activeadmin 的最简单方法是什么?
理想情况下,我想要一个允许我输入 smith .edu
或 smith AND .edu
以过滤包含这两个术语的电子邮件的小部件。
只需向您的模型添加三个过滤器:
filter :email_cont
filter :email_start
filter :email_end
它为您提供了一种灵活的方式来管理您的搜索。
此过滤器执行下一个 sql 代码:
SELECT "admin_users".* FROM "admin_users"
WHERE ("admin_users"."email" ILIKE '%smith%' AND
"admin_users"."email" ILIKE '%\.edu')
ORDER BY "admin_users"."id" desc LIMIT 30 OFFSET 0
我希望这正是您要找的。
我找到了一个解决方案,但它并不完美。
好消息是 Ransack 可以轻松进行多词搜索。这些搜索使用 'predicate' cont_all
。以下行用于查找包含 'smith' 和 '.edu'.
User.ransack(email_cont_all: ['smith','.edu'] ).result
由于这些搜索在 Ransack 中很容易,因此在 Activeadmin 中可能也很简单,对吧?错误的!为了让它们正常工作,我需要做三件事。
我把一个自定义的搜索方法(a.k.a。ransacker)放到了
User.rb
。我将劫掠者命名为email_multiple_terms
。class User < ActiveRecord::Base # ... ransacker :email_multiple_terms do |parent| parent.table[:path] end
我在我的 activeadmin 仪表板中声明了一个过滤器,并将其与劫掠者相关联。请注意,搜索谓词
cont_all
附加到劫掠者名称。
admin/User.rb
:
ActiveAdmin.register User do
# ...
filter :email_multiple_terms_cont_all, label: "Email", as: :string
此行在 Activeadmin 中创建过滤器小部件。我们快到了。剩下的一个问题:Activeadmin 将搜索查询作为单个字符串(例如 "smith .edu"
)发送给搜查,而我们的搜查者希望将搜索词作为一个数组。在某处,我们需要将单个字符串转换为搜索词数组。
我修改了 activeadmin 以在特定条件下拆分搜索字符串。逻辑在我添加到 lib/active_admin/resource_controller/data_access.rb.
的方法中def split_search_params(params) params.keys.each do |key| if key.ends_with? "_any" or key.ends_with? "_all" params[key] = params[key].split # turn into array end end params end
然后我在apply_filtering
里面调用了这个方法。
def apply_filtering(chain)
@search = chain.ransack split_search_params clean_search_params params[:q]
@search.result
end
此代码存在于我自己的 activeadmin 分支中,此处:https://github.com/d-H-/activeadmin
因此,要进行多词搜索,请按照上面的步骤 1 和 2 进行操作,并包括我的 A.A 分支。在你的 Gemfile 中:
gem 'activeadmin', :git => 'git://github.com/d-H-/activeadmin.git'
HTH.
如果谁有更简单的方法,请分享!
有一个使用 ranasckable 范围的简单解决方案
所以在你的模型中加入这样的东西
class User < ActiveRecord::Base
....
scope :email_includes, ->(search) {
current_scope = self
search.split.uniq.each do |word|
current_scope = current_scope.where('user.email ILIKE ?', "%#{word}%")
end
current_scope
}
def self.ransackable_scopes(auth_object = nil)
[ :email_includes]
end
end
之后您可以使用 AA DSL 添加过滤器
喜欢
filter :email_includes, as: :string, label: "Email"
UPD
如果将 email_contains_any
更改为 email_includes