免责声明:https://github.com/dubadub/filtered 的作者在这里。
ActiveRecord 为关系提供merge 方法。它与两个查询部分相交,这允许将查询逻辑分成几部分。
基于这个想法,我创建了一个 gem https://github.com/dubadub/filtered。
在你的情况下,它可能是这样的:
# app/controllers/people_controller.rb
class PeopleController < ApplicationController
before_action :set_filter
def index
@people = People.all.merge(@filter)
end
private
def set_filter
@filter = PersonFilter.new(filter_params)
end
def filter_params
params.fetch(:filter, {}).permit(:age, :active, :sorting)
end
end
# app/filters/person_filter.rb
class PersonFilter < ApplicationFilter
field :age
field :active do |active|
-> { joins(:memberships).merge(Membership.where(active: active)) }
end
field :sorting do |value|
order_by, direction = value.values_at("order", "direction")
case order_by
when "name"
-> { order(name: direction) }
when "age"
-> { order(age: direction) }
else
raise "Incorrect Filter Value"
end
end
end
# app/views/people/index.slim
= form_for(@filter, url: search_path, method: "GET", as: :filter) do |f|
.fields
span Age
= f.select :age, (18..90).map { |a| [ a, a ] }
.fields
span Active
= f.check_box :active
.fields
span Sorting
span Name
= f.radio_button :sorting, "name asc"
= f.radio_button :sorting, "name desc"
span Age
= f.radio_button :sorting, "age asc"
= f.radio_button :sorting, "age desc"
.actions
= f.submit "Filter"
希望对你有帮助!