frcake frcake - 2 months ago 10
Ruby Question

Ruby on Rails Solr - Multiple facets

I'm trying to implement facets in a way that when you choose one , all the others don't get canceled so i can have 2 at the same time.

My site has classifieds so for example if i have a classified

"Fender Bass"
, a classified
"Fender Stratocaster"
and a classified
"Gibson Bass"
if i choose the facet
Bass
im able to see both basses but then i'd like to filter deeper and choose
Fender
now if i do that , ill get
"Fender Stratocaster"
and
"Fender Bass"
and the
Bass
facet will not be active , what i intend to do is go from
Bass
deeper to only
"Fender Bass"
when choosing
Fender
after
Bass


My schema:

create_table "classifieds", force: :cascade do |t|
t.string "make"
t.string "model"
t.string "year"
t.string "color"
t.string "title"
t.string "condition"
t.string "price"
t.string "offer"
t.string "make_country"
t.text "description"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "category_id"
t.index ["category_id"], name: "index_classifieds_on_category_id"
t.index ["user_id"], name: "index_classifieds_on_user_id"
end


My model:

class Classified < ApplicationRecord


belongs_to :user
belongs_to :category
has_many :photos, dependent: :destroy, inverse_of: :classified

has_many :favorite_classifieds, dependent: :destroy
has_many :favorited_by , through: :favorite_classifieds , source: :user #for the favorite_by to work :source is needed

accepts_nested_attributes_for :photos


searchable do
text :title, :boost => 5
text :model , :created_month , :make

time :created_at


string :created_month
string :make
string :model
end

def created_month
created_at.strftime("%B")
end



end


My Controller:

def index

@search = Classified.search do
fulltext params[:search]
with(:created_at)

facet :model
with(:model , params[:model]) if params[:model].present?
facet :make
with(:make , params[:make]) if params[:make].present?
facet :created_month
with(:created_month , params[:month]) if params[:month].present?

end
@classified = @search.results

end


View.html.erb

<div class="col-md-9 visible-lg">
<div class="facets">

<h6>Μοντέλο</h6>
<ul>
<% for row in @search.facet(:model).rows %>
<li>
<% if params[:model].blank? %>
<%= link_to row.value, :model => row.value %> (<%= row.count %>)
<% else %>
<strong><%= row.value %></strong> (<%= link_to "remove", :model => nil %>)
<% end %>
</li>
<% end %>
</ul>

<h6>Μάρκα</h6>
<ul>
<% for row in @search.facet(:make).rows %>
<li>
<% if params[:make].blank? %>
<%= link_to row.value, :make => row.value %> (<%= row.count %>)
<% else %>
<strong><%= row.value %></strong> (<%= link_to "remove", :make => nil %>)
<% end %>
</li>
<% end %>
</ul>
</div>
</div>


Any help greatly appreciated!

Answer

ok i ended up with this , this works for multiple facets in rails 5!

controller : def index

    @search = Classified.search do 
        paginate(:page => params[:page] || 1, :per_page => 10)
        order_by(:created_at , :desc)
        fulltext params[:search]
        with(:created_at)

        active_model = with(:model ,params[:model]) if params[:model].present?

        active_make = with(:make , params[:make]) if params[:make].present?

        active_make_country = with(:make_country , params[:make_country]) if params[:make_country].present?

        active_condition = with(:condition,params[:condition]) if params[:condition].present?

        active_category = with(:cat,params[:cat]) if params[:cat].present?

        facet(:model)   



        facet(:make)            


        facet(:make_country)

        facet(:condition)

        facet(:cat)


        facet :created_month
        with(:created_month , params[:month]) if params[:month].present?

    end
    @classifieds = @search.results

end

and in the view :

<div class="facets">            


            <h6>Μάρκα</h6>
            <ul class="facetlist">
                <% for row in @search.facet(:make).rows %>
                    <li>
                    <% if params[:make].blank? %>
                        <%= link_to(row.value, params.merge(:page  => 1,:make => row.value).permit!) %> <small class="rowcount"><%= row.count %></small>
                        <% else %>
                        <strong><%= row.value %></strong> (<%= link_to "remove", :make => nil %>)
                    <% end %>
                    </li>
                <% end %>
            </ul>

            <h6>Χώρα Κατασκευής</h6>
            <ul class="facetlist">
                <% for row in @search.facet(:make_country).rows %>
                    <li>
                    <% if params[:make_country].blank? %>
                        <%= link_to(row.value, params.merge(:page  => 1,:make_country => row.value).permit!) %> <small class="rowcount"><%= row.count %></small>
                        <% else %>
                        <strong><%= row.value %></strong> (<%= link_to "remove", :make_country => nil %>)
                    <% end %>
                    </li>
                <% end %>
            </ul>

            <h6>Κατάσταση</h6>
            <ul class="facetlist">
                <% for row in @search.facet(:condition).rows %>
                    <li>
                    <% if params[:condition].blank? %>
                        <%= link_to(row.value, params.merge(:page  => 1,:condition => row.value).permit!) %> <small class="rowcount"><%= row.count %></small>
                        <% else %>
                        <strong><%= row.value %></strong> (<%= link_to "remove", :condition => nil %>)
                    <% end %>
                    </li>
                <% end %>
            </ul>

            <h6>Κατηγορία</h6>
            <ul class="facetlist">
                <% for row in @search.facet(:cat).rows %>
                    <li>
                    <% if params[:cat].blank? %>
                        <%= link_to(row.value, params.merge(:page  => 1,:cat => row.value).permit!) %> <small class="rowcount"><%= row.count %></small>
                        <% else %>
                        <strong><%= row.value %></strong> (<%= link_to "remove", :cat => nil %>)
                    <% end %>
                    </li>
                <% end %>
            </ul>

        </div>

what happens is that in rails 5 , where you can't attr_accessor you have to use .permit! at the end of the merge in order to work!

<%= link_to(row.value, params.merge(:page  => 1,:cat => row.value).permit!) %>

i hope this helps someone else :)

Comments