frcake frcake - 2 months ago 6
Ruby Question

Ruby on Rails SOLR facets between 2 models

In my classifieds app , my "main" model is

Classifieds
but i have also implemented categorization so
Categories has_many :classifieds


Also i have implemented my
Categories
with
awesome_nested_set


And i have Solr search too!

In my sites
Classifieds - index.html.erb
i render the Classifieds and if search is used i render the corresponding Classifieds.

Now i have implemented a navbar which uses the
Category
model for navigation.
The navbar shows the Category.roots and the descendants of each root with a dropdown. This leads to the
Category - show.html.erb
,where
Classifieds
are shown according to the
Category
they are in!

So the question is here:
In my
Classifieds - index.html.erb
i have successfully implemented Solr facets , which are used as filters but this only works when the user either Searches or just filters in the initial index! So in simple words when he interacts with the
Classifieds Controller
.

How can i preserve the facet functionality when the user uses the navbar , which means he then interacts with the
Category controller


Models:

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 , :make_country , :condition ,:treecat,:cat,:price #TO BE CHANGED TO CURRENCY FORMAT

time :created_at

string :treecat
string :price #TO BE CHANGED TO CURRENCY FORMAT
string :created_month
string :cat
string :make_country
string :condition
string :make
string :model
end

def cat
category.root.name
end

def treecat
category.name unless category.name == category.root.name
end

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



class Category < ApplicationRecord

acts_as_nested_set
has_many :classifieds
end




Classifieds controller index action
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?

active_subcategory = with(:treecat,params[:treecat]) if params[:treecat].present?

facet(:model)
facet(:make)
facet(:make_country)
facet(:condition)
facet(:cat , exclude: active_subcategory)
facet(:treecat)
end
@classifieds = @search.results
end


Categories controller show action

def show
@category = Category.find_by_id(params[:id])
end


Classifieds - index.html.erb

<div class="indexbox">
<div class="col-md-2 col-md-offset-1 visible-lg">
<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>

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

</div>
</div>




<% @classifieds.each do |f| %>
<% if !f.sold %>

<div class="center-div" id="index">

<div class="col-lg-12">

<div class="pull-right">
<div class="listingoptions">
<div class="col-md-3">
<p><%= link_to "", new_classified_message_path(:recipient_id => f.user_id , :classified_id => f.id), :class => "glyphicon glyphicon-envelope" , :style => "color:#EFCE7B" %></p>

<%if current_user.favorite_classifieds.collect(&:classified_id).include?(f.id) %>

<p><%= link_to "", favorite_classified_path(f, type: "unfavorite") , :class => "glyphicon glyphicon-heart" , :style => "color:#FF0000", method: :put %></p>

<%else%>

<p><%= link_to "", favorite_classified_path(f, type: "favorite") , :class => "glyphicon glyphicon-heart-empty" , :style => "color:#000000", method: :put %></p>

<%end%>

<p><%= link_to "", editlisting_path(f) , :class => "glyphicon glyphicon-flag" , :style => "color:#EB573B" %></p>

</div>
</div>
</div>

<%= link_to classified_path(f) , :class => "link" do %>
<div class="media">
<div class="mediabox">

<div class="media-left" href="#">


<!-- <img class="media-object" src="..." alt="Generic placeholder image">-->
<% if f.photos.first %>
<%= image_tag f.photos.first.image.url , :class => "media-object"%>

<%end%>

</div>
<div class="media-body">
<h5 class="media-heading"> <%= f.title %></h5>
<small><%= f.created_month %></small>
<% if f.category.parent_id? %>
<small><%= f.category.root.name %></small>
<%end%>
<small><%= f.category.name %></small>
<div class="price ">
<h5><%= f.price %> </h5>

</div>
</div>
</div>
</div>
</div>

</div>



<%end%>
<%end%>
<%end%>

<div class="center-div">
<div class="digg_pagination">
<%= will_paginate @classifieds , :previous_label => '<', :next_label => '>' %>
</div>
</div>



</div>


Categories show.html.erb

<div class="indexbox">
<div class="center-div" id="index">

<div class="categorytitle">
<h4>
<%= @category.root.name %>
<% unless @category.name == @category.root.name %>
<span> >> </span><%= @category.name %>

</h4>
<%end%>
</div>
</div>

<% @category.self_and_descendants.each do |desc| %>
<% desc.classifieds.each do |f|%>

<% if !f.sold %>

<div class="center-div" id="index">

<div class="col-lg-12">

<div class="pull-right">
<div class="listingoptions">
<div class="col-md-3">
<p><%= link_to "", new_classified_message_path(:recipient_id => f.user_id , :classified_id => f.id), :class => "glyphicon glyphicon-envelope" , :style => "color:#EFCE7B" %></p>

<%if current_user.favorite_classifieds.collect(&:classified_id).include?(f.id) %>

<p><%= link_to "", favorite_classified_path(f, type: "unfavorite") , :class => "glyphicon glyphicon-heart" , :style => "color:#FF0000", method: :put %></p>

<%else%>

<p><%= link_to "", favorite_classified_path(f, type: "favorite") , :class => "glyphicon glyphicon-heart-empty" , :style => "color:#000000", method: :put %></p>

<%end%>

<p><%= link_to "", editlisting_path(f) , :class => "glyphicon glyphicon-flag" , :style => "color:#EB573B" %></p>

</div>
</div>
</div>

<%= link_to classified_path(f) , :class => "link" do %>
<div class="media">
<div class="mediabox">

<div class="media-left" href="#">


<!-- <img class="media-object" src="..." alt="Generic placeholder image">-->
<% if f.photos.first %>
<%= image_tag f.photos.first.image.url , :class => "media-object"%>

<%end%>

</div>
<div class="media-body">
<h5 class="media-heading"> <%= f.title %></h5>
<small><%= f.created_month %></small>

<% if f.category.parent_id? %>
<small><%= f.category.root.name %></small>
<%end%>

<small><%= f.category.name %></small>
<div class="price ">
<h5><%= f.price %> </h5>

</div>
</div>
</div>
</div>
</div>

</div>



<%end%>
<%end%>
<%end%>

<%end%>
</div>


im a noob , i know there's stuff wrong with my indentation in html , sorry for that!

Answer

Ok i did it by nesting routes and taking some fields from the categories model.

    resources :categories do
      resources :classifieds do 
      end
    end

Category model:

 def nested_classifieds
    Classified.where(category_id: self_and_descendants.select(:id))
end

def nested_categories
    self_and_descendants    
end

Classifieds controller

def index
    if @category.present? 
      @classifieds = @category.nested_classifieds 
      nested_categories = []
      @category.nested_categories.each do |f|
        nested_categories << f.id
      end

      @search = Sunspot.search(Classified ) do 
        paginate(:page => params[:page] || 1, :per_page => 10)
        order_by(:created_at , :desc)
        fulltext params[:search]    
        with(:categoryid,nested_categories)
        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?
        active_subcategory = with(:treecat,params[:treecat]) if params[:treecat].present?
        active_pricerange = with(:price, params[:price]) if params[:price].present?

        fulltext params[:prc]
        facet :price
        with(:price).less_than(1000)

        facet(:model) 
        #facet(:model , exclude: active_condition)      
        facet(:make)      
        facet(:make_country)    
        facet(:condition)   
        facet(:cat)   
        facet(:treecat)     
      end
      @classifieds = @search.results  
        else
          #redirect_to '/'
          #@classified=@search.results
          search
    end
  end
Comments