0

On the main page, I have a list of videos and pictures. Those videos & pictures belongs to a category. So, I have a filter for the category and one for the type(vidéos or pictures). The problem is that I can't use both filter at the same time without altering the first one. If for example I want to show only the picture and then I want a specific category, I get all pictures and videos from the category selected.
Exemple with a filter of pictures :
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 %>

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 } ) %>");


EDIT - Exemple for categories :
view/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 %>

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 } ) %>");
KingOfBabu
  • 409
  • 3
  • 21
  • You can use two select tag, one for category and one for type and a submit button for search – Ankit Pandey Apr 19 '17 at 11:48
  • Category filter is also a link? Filters are applied one at a time? It will help if you share complete code (i.e. for both filters, no just one). – Gerry Apr 19 '17 at 12:35
  • Yes, this is two link and they are not applied at the same time. The filter for category is similar to this one. – KingOfBabu Apr 19 '17 at 12:42

3 Answers3

2
  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

Now you just need to pass something like checkboxes to enable content

Marcos R. Guevara
  • 5,258
  • 6
  • 19
  • 44
2

if you have created search form_tag

just add toggle form/checkboxes for each type then add the condition in controller

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

I expected the url will be like this

yourhostname/yourmodels?utf8=✓&picture=boolean&video=boolean&category=integer
buncis
  • 2,148
  • 1
  • 23
  • 25
1

If i understand correctly, the problem seems to be that your app doesn't remember the value of previous filter.

You can simulate this by sending the selected filters as parameters and adding them to your links, so the next request will get the value of the previous filter (if any).

There is no need to use separate actions, the filters can be applied with just one action in your controller (i used show_media in my example), you just need to check params to show the right information.

# 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

Here you are setting the values for @pictues or @videos, but instead of using two actions, you just check the type to set one or the other.

The method media receives the model object (Video or Picture) to be used and returns the related model records depending if category is provided or not (this helps you DRY your code a little).

Next, you must update your links to include both type and category, this needs to be done in both index.html.erb and show_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 %>

We added type to pictures and videos (no category since none is selected yet), and a couple of attributes (data-category-id and class) to your categories links to be able to identify them on 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");
});

The added lines will modify your links to include both type and category parameters depending on what have you requested before, using the @category and @type variables created in your controller.

Now, no matter what you click first, you will always pass the correct selected filters to your controller without losing them every time.

Gerry
  • 10,337
  • 3
  • 31
  • 40