Set*_*itt 5 parameters controller ruby-on-rails filterrific
我终于让我的过滤器开始工作了,它是一个很棒的宝石,即使对于像我这样的菜鸟来说,也算是有点复杂。
我原来的索引页面是根据用户附近的活动记录来过滤活动记录,如下所示:
def index
location_ids = Location.near([session[:latitude], session[:longitude]], 50, order: '').pluck(:id)
@vendor_locations = VendorLocation.includes(:location).where(location_id: location_ids)
@appointments = Appointment.includes(:vendor).
where(vendor_id: @vendor_locations.select(:vendor_id))
end
Run Code Online (Sandbox Code Playgroud)
因此,这将拉动该区域中所有带有供应商的约会,但是如何将其传递给Filterrific搜索:
@filterrific = initialize_filterrific(
params[:filterrific],
select_options:{ sorted_by: Appointment.options_for_sorted_by, with_service_id: Service.options_for_select },
) or return
@appointments = @filterrific.find.page(params[:page])
respond_to do |format|
format.html
format.js
end
Run Code Online (Sandbox Code Playgroud)
似乎Filterrerrific默认情况下正在加载所有约会,但我想限制在附近的约会。我想念什么?
您似乎缺少的是default_filter_params模型中过滤宏的参数。(您的问题没有提到您对VendorLocation模型进行了任何调整,因为这是您要过滤的对象,因此应在此调用该宏。也许您只是将其从问题中省略了...)
从模型文档:
filterrific(
default_filter_params: { sorted_by: 'created_at_desc' },
available_filters: [
:sorted_by,
:search_query,
:with_country_id,
:with_created_at_gte
]
)
Run Code Online (Sandbox Code Playgroud)
您可能已经在文档的第一页上找到了它,但是示例应用程序中还需要一些更重要的内容(当我最近第一次使用Filterrific时,我也遇到了这个问题。)
起始页上的信息不足以使您真正入门。您需要进一步阅读以了解更改模型,模型访问和视图以支持Filterrific可能需要的其他方法。
使默认过滤器设置有效的部分是此default_filter_params散列(NOT select_options,它为“选择” aka下拉框提供选项。这根本不是您想要的,除非您正在执行下拉过滤器。)此散列包含一个列表默认情况下需要应用的范围(哈希键),并且scope参数用作哈希值。
这default_filter_params散列可能不是你唯一缺少的......你还必须定义这些ActiveRecord的作用域对于每个滤波器的要在模型中使用,并在这些名称available_filters按上述方法,并提供给filterrific:
scope :with_created_at_gte, lambda { |ref_date|
where('created_at >= ?', ref_date)
end
Run Code Online (Sandbox Code Playgroud)
这些作用域都必须带有一个参数,这一点很重要(该值来自视图页面上过滤器字段的值,即使您希望对用户隐藏它们,也必须将它们添加到视图中)。同样重要的是,它们始终返回ActiveRecord关联。
这更像您想要的:
scope :location_near, lambda { |location_string|
l = Location.near(location_string).pluck(:id)
where(location_id: l)
end
Run Code Online (Sandbox Code Playgroud)
这种方法的问题是,在您的情况下,没有location_string或任何单个位置变量,因此您的位置参数具有多个坐标。但是您根本不是第一个遇到此问题的人!
该问题几乎完全描述了您要解决的问题。Filterrific的作者建议将location字段嵌入到nested中的隐藏表单字段中fields_for,以便表单仍可以将单个参数传递给范围(如with_distance_fields):
<%= f.fields_for :with_distance do |with_distance_fields| %>
<%= with_distance_fields.hidden_field :lat, value: current_user.lat %>
<%= with_distance_fields.hidden_field :lng, value: current_user.lng %>
<%= with_distance_fields.select :distance_in_meters,
@filterrific.select_options[:with_distance] %>
<% end %>
Run Code Online (Sandbox Code Playgroud)
...在您的视图中进行更改,并添加一个类似于以下内容的匹配范围(从链接的GitHub问题复制):
scope :with_distance, -> (with_distance_attrs) {
['lng' => '-123', 'lat' => '49', 'distance_in_meters' => '2000']
where(%{
ST_DWithin(
ST_GeographyFromText(
'SRID=4326;POINT(' || courses.lng || ' ' || courses.lat || ')'
),
ST_GeographyFromText('SRID=4326;POINT(%f %f)'),
%d
)
} % [with_distance_attrs['lng'], with_distance_attrs['lat'], with_distance_attrs['distance_in_meters']])
}
Run Code Online (Sandbox Code Playgroud)
因此,您的 :with_distance范围应进入VendorLocation模型,并且可能看起来像这样:
scope :with_distance, -> (with_distance_attrs) {
lat = with_distance_attrs['lat']
lng = with_distance_attrs['lng']
dist = with_distance_attrs['distance']
location_ids = Location.near([lat, lng], dist, order: '').pluck(:id)
where(location_id: location_ids)
end
Run Code Online (Sandbox Code Playgroud)
最后但并非最不重要的一点是,您可能已经注意到我删除了对的调用includes(:location)-我知道您是故意将它放在那儿的,并且我在文档中没有很清楚地看到它,但是您仍然可以急于加载并将ActiveRecord优化到通过以这种方式定义控制器的index方法,将过滤器工作传递给Filterrific之前的单个查询:
def index
@appointments = Appointment.includes(:vendor).
filterrific_find(@filterrific).page(params[:page])
end
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助!