I am working on a faceted search in rails. It follows from my previous question: Rails: How to use facets with search results
What I am able to do is to use scopes to get all the facets with respect to the search results as shown in the figure:
What I am currently working on is use the facets texts as a link to add extra params to the search result we already got.
I have two questions in regard to this:
- How to take existing search URL and add a link to add/merge params when a link is clicked. I am using params merge which is not working. The code is as below.
<h3 style = "color:#7C064D; text-align: center;"><strong>CYLINDER</strong></h3>
<%- @listings_cylinder.each do |key, value| -%>
<h5 style = "color:#F00000; text-align: left;"><strong><%= link_to "#{key.upcase if key} (#{value})" , search_listings_path(params.merge(:cylinder => "#{key}")) %> </strong></h5>
<% end %>
- How to use multiple filters at the same time. What I want is when a facet link is clicked, it should add a small filter link below the sorting link in the pic. When a user wants to undo that facet filter effect, he clicks the X on that small link and he gets to the search query without the filter. The same what happens on hotels.com or priceline.com as shown:
Note: I don't want to use solr/elaticsearch because it's not the best use case here. I want to learn it from scratch. I am already able to build facets texts with simple rails. With a little help, I will be able to do it.
Codes:
Scopes I am using:
scope :listing_search_cities, -> {group(:city).count}
scope :listing_search_body_type, -> {group(:bodytype).count}
scope :listing_search_states, -> {group(:state).count}
scope :listing_search_newused, -> {group(:NewUsed).count}
scope :listing_search_transmission, -> {group(:transmission).count}
scope :listing_search_cylinder, -> {group(:cylinder).count}
scope :listing_search_fuel, -> {group(:fuel).count}
scope :listing_search_drive, -> {group(:drive).count}
scope :listing_search_trim, -> {group(:trim).count}
scope :listing_search_color, -> {group(:color).count}
scope :listing_search_year, -> {group(:year).count}
scope :listing_search_interiorcolor, -> {group(:interiorcolor).count}
In the controller search action, I am using:
def search
@listings = Listing.search(params)
@listings_cities = @listings.listing_search_cities
@listings_bodytype = @listings.listing_search_body_type
@listings_states = @listings.listing_search_states
@listings_newused = @listings.listing_search_newused
@listings_cylinder = @listings.listing_search_cylinder
@listings_transmission = @listings.listing_search_transmission
@listings_drive = @listings.listing_search_drive
@listings_trim = @listings.listing_search_trim
@listings_fuel = @listings.listing_search_fuel
@listings_color = @listings.listing_search_color
@listings_interiorcolor = @listings.listing_search_interiorcolor
@listings_year = @listings.listing_search_year
end
In view, I am using iteration through the key values like this:
<%- @listings_cylinder.each do |key, value| -%>
<h5 style = "color:#F00000; text-align: left;"><strong><%= link_to "#{key.upcase if key} (#{value})" , search_listings_path(params.merge(:cylinder => "#{key}")) %> </strong></h5>
<% end %>
Not the solution, but some ideas (not tested):
Pass all filters to the search method in a hash in params (such as params[:filters]).
Define an instance variable with all the filters and load it in the search method in the controller.
Filter the listing based on filters.
def search
@current_filters = params[:filters]
@listings = Listing.all
@listings = @listings.where(:cylinder => @current_filters[:cylinder]) if @current_filters[:cylinder]
@listings = @listings.where(:fuel => @current_filters[:fuel]) if @current_filters[:fuel]
#etc
end
In the view:
<% @listings_cylinder.each do |key, value| %>
<h5><%= link_to "#{key.upcase if key} (#{value})", search_listings_path(filters: @current_filters.merge(:cylinder => "#{key}")) %>
</h5>
<% end %>
In the view, when showing current filters:
Applied filters:
<ul>
<% @current_filters.each do |key, value| %>
<li><%= link_to value, search_listings_path(filters: @current_filters.except(key)) %>
</li>
<% end %>
</ul>