Rails 5 - 具有最新has_many关联的范围



我正在为我的用户模型创建一个过滤表。我创建了一些范围来过滤它们。我是 :

class User < ApplicationRecord
has_many :invoices
scope :application_approved, -> { ... }
scope :application_denied, -> { ... }
scope :latest_invoice_paid, -> { ... }
scope :latest_invoice_not_paid, -> { ... }
def self.__self__
self
end
end

在控制器中:

def index
filters = params[:statuses] || {}
application_status = filters[:application_status].presence
payments_status = filters[:payments_status].presence
@vehicles = Vehicle.send(application_status || :__self__)
.send(payment_status || :__self__)
.paginate(:page => params[:page], :per_page => 10)
.order('created_at DESC')
end

所有筛选器都独立工作,但是当链接时,未应用的筛选器似乎会抵消早期的筛选器。

例如,如果我将过滤器设置为仅显示已付款的用户,则它可以工作。但是,如果我将过滤器设置为仅显示已批准/未批准的用户,则所有用户将始终返回。似乎在未应用过滤器时返回self只是返回所有用户。

那么,如果未应用过滤器,如何跳过范围?

像这样的东西应该可以解决问题,它还有助于保护您的发送方法。因为只能执行列入白名单的方法。下面的代码执行以下操作:

  1. 首先使用允许的密钥和允许的值创建白名单。
  2. 获取params[:statuses],如果不存在,则创建新的参数对象。
  3. 仅允许允许的密钥。
  4. 删除所有没有列入白名单值的键值实例。
  5. 将允许的参数转换为哈希。
  6. 减少生成的集合。从Vehicle.all开始,然后发送列入白名单的方法(将它们链接在一起(。如果键或值不存在,则不会循环,因此无需调用:__self__:itself
  7. 做你剩下的逻辑。

def index
whitelist = ActiveSupport::HashWithIndifferentAccess.new(
application_status: %w[application_approved application_denied],
payments_status: %w[latest_invoice_paid latest_invoice_not_paid],
)
filters = params[:statuses] || ActionController::Parameters.new
@vehicles = 
filters
.permit(*whitelist.keys)
.select { |key, value| whitelist[key].include?(value) }
.to_h
.reduce(Vehicle.all) { |vehicles, (_key, value)| vehicles.send(value) }
.order(created_at: :desc)
.paginate(page: params[:page], per_page: 10)
end

引用:

  • ActiveSupport::HashWithIndifferentAccess
  • 动作控制器::P arameter(许可选择to_h都可以在这里找到(
  • 可枚举#减少
  • 板片运算符*.permit(*whitelist.keys)

最新更新