Ruby on Rails - 在视图中为同一数据使用两个不同的过滤器
Ruby on Rails - 在视图中为同一数据使用两个不同的过滤器
在主页面上,我有一个视频和图片的列表。这些视频和图片属于一个类别。因此,我有一个用于类别的过滤器和一个用于类型(视频或图片)的过滤器。问题是,我不能同时使用这两个过滤器,而不改变第一个过滤器。例如,如果我只想显示图片,然后想要一个特定的类别,我会得到所选类别的所有图片和视频。示例中的图片过滤器:
查看/galeries/index.html.erb
<%= link_to show_pictures_path, :remote => true, :id => "btn-pictures", :class => "btn btn-default" do %> 图片 <% end %>
controller/galeries_controller.rb
def show_pictures @selected = Picture.order('created_at DESC') end
view/galeries/show_pictures.js.erb
$("#media_filter").html("<%= escape_javascript(render partial: 'partials/media_filter', locals: { medias: @selected } ) %>");
编辑-类别示例:
view/galeries/index.html.erb
<% @categories.each do |c| %>
controller/galeries_controller.rb
def show_categories @videos = Video.joins(:media).where("medium.category_id = ?", params[:id]) @pictures = Picture.joins(:media).where("medium.category_id = ?", params[:id]) end
view/galeries/show_categories.js.erb
$("#media_filter").html("<%= escape_javascript(render partial: 'partials/media_filter', locals: { medias: @videos} ) %>"); $("#media_filter").append("<%= escape_javascript(render partial: 'partials/media_filter', locals: { medias: @pictures } ) %>");
问题的原因是应用程序没有记住之前筛选器的值。解决方法是通过将所选的筛选器作为参数发送,并将它们添加到链接中,以便下一次请求能够获取先前筛选器的值(如果有的话)。不需要使用单独的动作,可以在控制器中的一个动作中应用筛选器(在示例中使用了show_media
),只需要检查params
以显示正确的信息。
在控制器galeries_controller.rb
中设置category
和type
的值,但不需要使用两个动作,只需检查type
以设置其中一个值。方法media
接收要使用的模型对象(Video
或Picture
)并根据是否提供category
返回相关的模型记录(这有助于使代码更加简洁)。
接下来,必须更新链接以包括type
和category
,这需要在index.html.erb
和show_media.js.erb
中完成。
在index.html.erb
中,添加type
到pictures
和videos
(没有category
因为还没有选择),并在类别链接中添加了一对属性(data-category-id
和class
)以便在show_media.js.erb
中识别它们。
在show_media.js.erb
中,添加的代码将根据之前的请求修改链接,根据控制器中创建的type
和category
变量来包含type
和category
参数。
现在,无论首先点击什么,都将始终将正确的选定筛选器传递给控制器,而不会每次都丢失它们。
在这个问题中,出现的原因是需要在视图中为相同的数据添加两个不同的过滤器。解决方法是在控制器中添加条件,并在视图中添加一个切换表单/复选框来控制过滤器的类型。
首先,在视图中创建一个搜索表单,然后为每种类型添加一个切换表单/复选框。然后,在控制器中添加条件来根据选择的过滤器类型查询数据。以下是示例代码:
def show_categories @pictures = Picture.joins(:media).where("medium.category_id = ?", params[:category]) if params[:picture] == 'true' @videos = Video.joins(:media).where("medium.category_id = ?", params[:category]) if params[:video] == 'true' end
期望的URL应该像这样:
yourhostname/yourmodels?utf8=✓&picture=boolean&video=boolean&category=integer
所以,使用这个解决方案,我需要用复选框替换link_to吗?你仍然可以使用link_to/button,但不要忘记将参数发送到控制器。你可以参考这个stackoverflow的链接来了解如何添加查询字符串参数到link_to:[add querystring parameters to link to](http://stackoverflow.com/questions/2695538)
在控制器中,你可以使用params[:video]和params[:picture]来获取过滤器的值。
这段代码中存在一个问题,即在视图中为相同的数据使用了两个不同的过滤器。这个问题的出现原因是在show_categories方法中,使用了两个条件语句来判断是否选中了视频和图片。
解决这个问题的方法是去除多余的条件判断语句。可以通过将两个条件合并为一个条件来实现。具体做法是使用一个变量来存储过滤条件,并在查询中使用这个变量。这样可以避免重复的代码和条件判断。
下面是修改后的代码:
def show_categories selected = params[:selected] # 获取选中的过滤条件,可以是视频或图片 if selected.present? = Medium.joins(:category).where("category.id = ? AND medium.type = ?", params[:id], selected) else = [] # 如果没有选中过滤条件,返回一个空数组 end end
现在只需要传递一个类似复选框的参数来启用内容过滤。这样就解决了问题,并且代码更加简洁和易读。