Filter list results with a primary filter "with multi" and a secondary filter "only one"

The title may seem confusing but ill explain what i want to implement.

What I want: I want a conatainer-list that contains all the "categories" in the agreement model called writing_type, So each agreement will have a writing_type by string. This container-list will have multiple different writing_types of course. By default all the writing types will be displayed. When selecting a or multiple writing_type's the list will filter the results to those writing_type's.

  • For example

  • page loaded and the list contains all writing types and all rows in DESC.

  • container-list that has the following writing types "onclick highlights selected writing_type blue, can select multiple, or deselect"

  • writing_types: {college_essay, college app, foreign language}

  • I select college_essay and foreign language

  • results come out with only the college essay and foreign language

  • next i click the button called filter by duedate

  • the results still will contain college_essay and foreign_language and will filter by duedate DESC.

  • there will be many different buttons besides due_date like create_at or price, however only one of these secondary filters may be selected at a time

-Now right next to the dropdown are buttons for the secondary filters

Currently this is the code i have right now with a drop-down but they all filter individually. Im not sure how to get the writing_type first and then by clicking one of the buttons such as created_at to filter.

enter image description here

<!-- filters for the categories -->
<div class="row text-center" style="margin:0;padding-bottom:10px;">
<div class="center" style="margin-left:18px;">
<div style="float:left;">
<%= link_to "Title", title_agreements_path, class: "link btn categories-button" %>
</div>
<!-- drop down with the writing types listed -->

<div class="agreements dropdown" style="float:left;margin-top:40px;">

<%= link_to '#', class:'btn categories-button dropdown-toggle', role:'button', style: 'text-decoration:none', 'aria-expanded' =>'false', data:{toggle: 'dropdown'} do %>
Writing Type
<span class="caret"></span>
<% end %>
<ul class="dropdown-menu" style="">


<h>Choose a Writing Type:</h>
<li><%= link_to "College Applications", collegeapplication_agreements_path, class: "link btn categories-button" %></li>
<li><%= link_to "College Essays", collegeessay_agreements_path, class: "link btn categories-button" %></li>
<li><%= link_to "Business Papers", businesspaper_agreements_path, class: "link btn categories-button" %></li>

<li><%= link_to "Resumes", resume_agreements_path, class: "link btn categories-button" %></li>
<li><%= link_to "Scholarship Essays", scholarshipessay_agreements_path, class: "link btn categories-button" %></li>
<li><%= link_to "High-School Essays", highschoolessay_agreements_path, class: "link btn categories-button" %></li>
<li><%= link_to "Language Translation", languagetranslation_agreements_path, class: "link btn categories-button" %></li>
</ul>
</div>

<div style="float:left;">
<%= link_to "Recent", recent_agreements_path, class: "link btn categories-button" %>
</div>
<div style="float:left;margin-top:40px;">
<%= link_to "Oldest", oldest_agreements_path, class: "link btn categories-button" %>
</div>


<div style="float:left;">
<%= link_to "Close Duedate", recentduedate_agreements_path, class: "link btn categories-button" %>
</div>
<div style="float:left;margin-top:40px;">
<%= link_to "Further Duedate", oldestduedate_agreements_path, class: "link btn categories-button" %>
</div>
<div style="float:left;">
<%= link_to "Lowest Price", lowestprice_agreements_path, class: "link btn categories-button" %>
</div>
<div style="float:left;margin-top:40px;">
<%= link_to "Highest Price", highestprice_agreements_path, class: "link btn categories-button" %>
</div>

</div>

</div>

routes.rb

 resources :agreements, path: "agreement" do
  collection do
    get :recent
    get :oldest
    get :recentduedate
    get :oldestduedate
    get :collegeapplication
    get :collegeessay
    get :businesspaper
    get :resume
    get :scholarshipessay
    get :highschoolessay
    get :languagetranslation
    get :title 
    get :lowestprice
    get :highestprice
 end
end

agreement.rb model

scope :recent, ->{ order("created_at DESC") }
scope :oldest, ->{ order("created_at ASC") }
scope :recentduedate, ->{ order("due_date DESC") }
scope :oldestduedate, ->{ order("due_date ASC") }
scope :lowestprice, ->{ order("current_price ASC") }
scope :highestprice, ->{ order("current_price DESC") }
scope :collegeapplication, ->{ where("writing_type = ?", "College Applications") }
scope :collegeessay, ->{ where("writing_type = ?", "College Essays") }
scope :businesspaper, ->{ where("writing_type = ?", "Business Papers") }
scope :resume, ->{ where("writing_type = ?", "Resumes") }
scope :scholarshipessay, ->{ where("writing_type = ?", "Scholarship Essays") }
scope :highschoolessay, ->{ where("writing_type = ?", "High-School Essays") }
scope :languagetranslation, ->{ where("writing_type = ?", "Language Translation") }
scope :title, ->{ order("title DESC") }
 def index
   @agreements = Agreement.where("accepted = ?", false).all.paginate(:page => params[:page], :per_page => 20)

 end

 def recent
  @agreements = Agreement.recent.where("accepted = ?", false).all.paginate(:page => params[:page], :per_page => 20)
  render action: :index
end

def oldest
  @agreements = Agreement.oldest.where("accepted = ?", false).all.paginate(:page => params[:page], :per_page => 20)
  render action: :index
end

def recentduedate
  @agreements = Agreement.recentduedate.where("accepted = ?", false).all.paginate(:page => params[:page], :per_page => 20) 
  render action: :index
end

def oldestduedate
  @agreements = Agreement.oldestduedate.where("accepted = ?", false).all.paginate(:page => params[:page], :per_page => 20) 
  render action: :index
end

def collegeessay
  @agreements = Agreement.collegeessay.where("accepted = ?", false).all.paginate(:page => params[:page], :per_page => 20) 
  render action: :index
end

def resume
  @agreements = Agreement.resume.where("accepted = ?", false).paginate(:page => params[:page], :per_page => 20) 
  render action: :index
end

def languagetranslation
  @agreements = Agreement.languagetranslation.where("accepted = ?", false).all.paginate(:page => params[:page], :per_page => 20) 
  render action: :index
end

def collegeapplication
  @agreements = Agreement.collegeapplication.where("accepted = ?", false).all.paginate(:page => params[:page], :per_page => 20) 
  render action: :index
end

def businesspaper
  @agreements = Agreement.businesspaper.where("accepted = ?", false).all.paginate(:page => params[:page], :per_page => 20) 
  render action: :index
end

def scholarshipessay
  @agreements = Agreement.scholarshipessay.where("accepted = ?", false).all.paginate(:page => params[:page], :per_page => 20) 
  render action: :index
end

def highschoolessay
      @agreements = Agreement.highschoolessay.where("accepted = ?", false).all.paginate(:page => params[:page], :per_page => 20) 
      render action: :index
    end



def title
  @agreements = Agreement.title.where("accepted = ?", false).all.paginate(:page => params[:page], :per_page => 20) 
  render action: :index
end

def lowestprice
  @agreements = Agreement.lowestprice.where("accepted = ?", false).all.paginate(:page => params[:page], :per_page => 20)
  render action: :index
end

def highestprice
  @agreements = Agreement.highestprice.where("accepted = ?", false).all.paginate(:page => params[:page], :per_page => 20)
  render action: :index
end

So far I have made this and it works all individually but i want the filter results to be based on what writing_type is selected as the primary result. Thank you!!!

Answers 1

  • Firstly, maybe use query parameters instead of individual path/actions since they are all doing the same thing using different conditions. This will simplify the code significantly.

    View

    <%= link_to "Resumes", agreements_path( writing_type: 'Resume', price_asc: true ) %>
    <%= link_to "Business Papers Cheapest First", agreements_path( writing_type: 'Business Papers', price_asc: true ) %>
    <%= link_to "Business Papers ", agreements_path( writing_type: 'Business Papers', price_desc: true ) %>
    

    The first link_to above will become "http://localhost:3000/agreements?writing_type=resume&price_asc=true"

    Then you can do this in the controller:

    def index
      @agreements = Agreement.where( accepted: false ).where( params[:writing_type] ).order( sorting )
    end
    
    private
      def sorting
        sort = []  # there is probably a smarter way to do this 
        sort << 'price    ASC' if params.has_key? :price_asc
        sort << 'price   DESC' if params.has_key? :price_desc
        sort << 'duedate  ASC' if params.has_key? :duedate_asc
        sort << 'duedate DESC' if params.has_key? :duedate_desc
        sort.join ', '
      end
    

    Then, if you need multiple selections, you can use a regular form or Javascript to build up the query and submit it.


Related Articles