主动管理员过滤器参数已传递给ransacker

问题描述

我正在尝试将几个ID传递给活动管理员自定义ransacker过滤器

   filter :hasnt_purchased_product_items_in,as: :select,collection: -> { ProductItem.all },multiple: true

洗劫者代码

ransacker :hasnt_purchased_product_items,formatter: proc { |product_id|
    users_who_purchased_ids = User.joins(:orders => :items).where("orders.status = 'success'").where("order_items.orderable_id IN (?)",product_id) # return only id-s of returned items.
    ids = User.where.not(id: users_who_purchased_ids).pluck(:id)
    ids.present? ? ids : nil # return ids OR nil!
} do |parent| # not sure why this is needed .. but it is :)
    parent.table[:id]
end 

这适用于单个查询,但不适用于多个查询sql会进行2次单独的搜索,而不是一次。

它正在运行以下2条语句

order.items.orderable_id IN ('90')

order.items.orderable_id IN ('91')

在2个单独的sql语句中,而不是我想要的是

order.items.orderable_id IN ('90','91')

活动管理页面中提交的信息是

q[hasnt_purchased_product_items_in][]: 90
q[hasnt_purchased_product_items_in][]: 91

我认为我需要在ransacker阶段对传入参数做些事情,但是我不确定如何处理

解决方法

不应该介入。参数应该是| product_ids |。并在proc中给我们一个数组对象,然后再使用它。您的抢劫犯应该返回一个活动记录关联或一个arel查询。

我将尝试其中的每一个:

  1. 在抢劫者名称中使用“ _in”,绕过数组逻辑。
ransacker :hasnt_purchased_product_items_in do |product_ids|
  users_who_purchased_ids = User.joins(orders: :items).where(orders: {status: 'success'},order_items: {orderable_id: product_ids}) # return only id-s of returned items.
  User.where.not(id: users_who_purchased_ids)
end
  1. 相同的抢劫犯名称,但使用块而不是格式化程序。
ransacker :hasnt_purchased_product_items do |product_ids|
  users_who_purchased_ids = User.joins(orders: :items).where(orders: {status: 'success'},order_items: {orderable_id: product_ids}) # return only id-s of returned items.
  User.where.not(id: users_who_purchased_ids)
end 

我不得不猜测该对象将返回,因为目前尚不清楚此抢劫犯所使用的模型。如果您可以告诉我目标(例如过滤用户的产品推荐以排除他们的购买),那么我可以更新答案。

  1. 创建范围并将其提供给搜查。

User.rb

  scope :hasnt_purchased_product_items_in,->(product_ids){
   users_who_purchased_ids = joins(orders: :items).where(orders: {status: 'success'},order_items: {orderable_id: product_ids}) # return only id-s of returned items.
   where.not(id: users_who_purchased_ids)
  }

  def self.ransackable_scopes(auth_object = nil)
    %i(hasnt_purchased_product_items_in)
  end

然后这有效:

User.ransack({hasnt_purchased_product_items_in: [[1,2,3]]}).result

请注意,背包需要一个args数组。我们需要一个arg,它是一个数组。