Ruby on Rails - 针对相同数据查看两个不同的过滤器

Posted

技术标签:

【中文标题】Ruby on Rails - 针对相同数据查看两个不同的过滤器【英文标题】:Ruby on Rails - Two different filter in view for the same data 【发布时间】:2017-04-19 11:10:31 【问题描述】:

在主页上,我有一个视频和图片列表。这些视频和图片属于一个类别。所以,我有一个类别过滤器和一个类型过滤器(视频或图片)。问题是我不能同时使用两个过滤器而不改变第一个过滤器。例如,如果我只想显示图片,然后我想要一个特定的类别,我会从所选类别中获取所有图片和 视频。 图片过滤器示例: view/galeries/index.html.erb

<%= link_to show_pictures_path, :remote => true, :id => "btn-pictures", :class => "btn btn-default" do %>
<em class="glyphicon glyphicon-picture"></em> Pictures
<% end %>

控制器/galeries_controller.rb

  def show_pictures
    @selected = Picture.order('created_at DESC')
  end

查看/galeries/show_pictures.js.erb

$("#media_filter").html("<%= escape_javascript(render partial: 'partials/media_filter', locals:  medias: @selected  ) %>");

编辑 - 类别示例: 查看/galeries/index.html.erb

<% @categories.each do |c| %>
  <li class="" id=btn-filter<%=c.id%>>
    <%= link_to show_categories_path(:id => c.id), :remote => true do %>
    <span class="badge pull-right"><%= Media.joins(:pictures).where(category_id: c.id).count + Media.joins(:videos).where(category_id: c.id).count  %></span> <%= c.name %>
    <% end %>
  </li>
<% end %>

控制器/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

查看/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  ) %>");

【问题讨论】:

您可以使用两个选择标签,一个用于类别,一个用于类型,一个用于搜索的提交按钮 类别过滤器也是链接?过滤器一次应用一个?如果您共享完整的代码(即两个过滤器,不只是一个),将会有所帮助。 是的,这是两个链接,它们不是同时应用的。类别过滤器与此类似。 【参考方案1】:
  def show_categories
     if selected_videos == true
      @videos = Video.joins(:media).where("medium.category_id = ?", params[:id])
     else
      @videos = [] # not the most clean but a way is to pass an empty array...
     end
     if selected_pictures == true
       @pictures = Picture.joins(:media).where("medium.category_id = ?", params[:id])
     else
      @pictures = [] # the same, empty array...
    end
  end

现在您只需传递复选框之类的内容即可启用内容

【讨论】:

老兄,你的姓氏很棒。仅出于这个原因投票 -)) 好吧,但这里不是开玩笑的网站@marmeladze,人们想解决。 我不是在开玩笑。您的答案会起作用,但不是一个好的解决方案。我刚刚为你的姓投票。 啊好吧,是的,是一个丑陋的解决方案 这是... == true 多余的。【参考方案2】:

如果您已创建搜索 form_tag

只需为每种类型添加切换表单/复选框,然后在控制器中添加条件

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

我预计网址会是这样的

yourhostname/yourmodels?utf8=✓&picture=boolean&video=boolean&category=integer

【讨论】:

所以使用这个解决方案,我需要将 link_to 替换为 checkbox ? @KingOfBabu 你仍然可以使用 link_to/button 但不要忘记将参数发送到控制器看到这个***.com/questions/2695538/… params[:video], params[:picture]【参考方案3】:

如果我理解正确,问题似乎是您的应用不记住先前过滤器的值。

您可以通过将所选过滤器作为参数发送并将它们添加到您的链接来模拟这一点,因此下一个请求将获得前一个过滤器的值(如果有)。

无需使用单独的操作,只需在控制器中执行一个操作即可应用过滤器(我在示例中使用了show_media),您只需检查params 即可显示正确的信息。

# controller/galeries_controller.rb

def show_media
  @category = params[:category]
  @type     = params[:type]
  @pictures = media(Picture) if @type == "pictures"
  @videos   = media(Video) if @type == "videos"
end

private
def media(model)
  if @category.blank?
    model.order('created_at DESC')
  else
    model.joins(:media).where("medium.category_id = ?", params[:id])
  end
end

您在此处设置@pictues@videos 的值,但不是使用两个操作,您只需检查type 以设置其中一个。

media 方法接收要使用的模型对象(VideoPicture)并根据是否提供 category 返回相关的模型记录(这有助于您稍微干燥代码)。

接下来,您必须更新您的链接以包含typecategory,这需要在index.html.erbshow_media.js.erb 中完成:

# index.html.erb

<%= link_to show_media_path(type: "pictures"), remote: true, id: "btn-pictures", class: "btn btn-default" do %>
    <em class="glyphicon glyphicon-picture"></em> Pictures
<% end %>

<%= link_to show_media_path(type: "videos"), remote: true, id: "btn-videos", class: "btn btn-default" do %>
    <em class="glyphicon glyphicon-video"></em> Videos
<% end %>

<% @categories.each do |c| %>
  <li class="" id="btn-filter<%= c.id %>">
    <%= link_to show_categories_path(id: c.id), remote: true, "data-category-id": c.id, class: "category-id" do %>
    <span class="badge pull-right"><%= Media.joins(:pictures).where(category_id: c.id).count + Media.joins(:videos).where(category_id: c.id).count  %></span> <%= c.name %>
    <% end %>
  </li>
<% end %>

我们将type 添加到picturesvideos(没有category,因为尚未选择任何一个),以及几个属性(data-category-idclass)到您的类别链接,以便能够在show_media.js.erb 上识别它们。

# show_media.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  ) %>");
$(#'btn-pictures').attr('href',"<%= show_media_path(type: 'pictures', category: @category) %>");
$(#'btn-videos').attr('href',"<%= show_media_path(type: 'pictures', category: @category) %>");
$('.category-id').each(function() 
  $(this).attr("href", "/show_media?type=<%= @type %>" + "&category=" + $(this).attr("data-category-id");
);

添加的行将修改您的链接以包含 typecategory 参数,具体取决于您之前请求的内容,使用在控制器中创建的 @category@type 变量。

现在,无论您首先单击什么,您始终会将正确选择的过滤器传递给您的控制器,而不会每次都丢失它们。

【讨论】:

以上是关于Ruby on Rails - 针对相同数据查看两个不同的过滤器的主要内容,如果未能解决你的问题,请参考以下文章

你好 postgres 数据库连接错误 Ruby on rails

如何使用相同的表单在 ruby​​ on rails 中创建和编辑

Ruby On Rails 很慢...?

Ruby on Rails 和 Netezza 后端

js.erb 文件正在执行两次。 Ruby on Rails - private_pub

第一个CRUD的制作方法(Ruby on Rails 開發秘籍 | Ruby on Rails 快速入門)