从 Active Admin 过滤器向 Ransack 发送参数

Sending parameter to Ransack from Active Admin filter

我正在尝试在 Active Admin 中对单个输入字段中客户的名字和姓氏进行筛选。 first_name 和 last_name 是单独的字段。

如果您有中间名,我的解决方案将失败。如果客户的名字是 "John H. Smith",那么 "John" 和 "Smith" 给出正确的结果,但是 "John Smith" 将找不到任何东西,因为额外的 'H.'.

ActiveAdmin.register Customer do
  ...
  filter :full_name_cont, label: 'Name', as: :string
end

# In the Customer model:

ransacker :full_name, formatter: proc { |full_name| full_name.downcase.to_s } do |parent|
     Arel::Nodes::InfixOperation.new('||',
          Arel::Nodes::InfixOperation.new('||',
             parent.table[:first_name], ' '
          ),
          parent.table[:last_name]
     )
end

所以现在我正在尝试将搜索词 "John H. Smith" 作为参数发送给 ransacker,这样我就可以将名称分成多个部分并搜索它们是否与名字或姓氏匹配:

ransacker :full_name, args: [:parent, :ransacker_args] do |parent, args|
   full_name = args.first
   search_items = full_name.split(" ")
   condition = "concat_ws(first_name, ' ', last_name) LIKE '%#{search_items.first}%'"
   search_items.each do |item|
      condition += " OR concat_ws(first_name, ' ', last_name) LIKE '%#{item}%'" if item != search_items.first
   end
   Arel.sql(condition)
end

不幸的是,args 总是空的。

有谁知道怎么给ransacker发送参数?

这个问题的解决方案是创建一个新的 Ransack 谓词,将空格视为通配符。

这一期也提出了这个想法:Make an OR with ransack

# In config/initializers/ransack.rb

Ransack.configure do |config|
  config.add_predicate 'contains',
         :arel_predicate => 'matches', # so we can use the SQL wildcard "%"
         # Format the incoming value: add the SQL wildcard character "%" to the beginning and the end of
         # the string, replace spaces by "%", and replace multiple occurrences of "%" by a single "%".
         # For using * and ? instead as wild cards use this #{Ransack::Constants.escape_wildcards(v).gsub("*", "%").gsub('?','_')}
         :formatter => proc {|v| ("%#{v.gsub(" ", "%")}%").squeeze("%")}
end

然后在模型中我使用了 https://github.com/activerecord-hackery/ransack/wiki/using-ransackers#5-search-on-a-concatenated-full-name-from-first_name-and-last_name-several-examples:

中示例中的搜查代码
# ActiveAdmin - customers.rb
# I re-open the model 
class Customer
  ransacker :full_name do |parent|
       Arel::Nodes::InfixOperation.new('||',
          Arel::Nodes::InfixOperation.new('||',
              parent.table[:first_name], ' '),
                  parent.table[:last_name])
  end
end

ActiveAdmin.register Customer do
...
end