title: Rails Sunspot gem: Usings facets with multiple model site-wide searches
body: <p>I'm trying to implement a sitewide search through the powerful Sunspot gem for Rails. This involves a search across multiple, very different models at once. What I WANT to do is use the faceting feature to allow the user to filter their search results on each model, or by default view all on the same page, interspersed with each other ordered by the :boost qualifier. Combining the faceting code from the <a href="http://asciicasts.com/episodes/278-search-with-sunspot" rel="nofollow noreferrer">Sunspot Railscast</a> with the multiple model searching code from another <a href="https://stackoverflow.com/questions/6037802/sunspot-with-multiple-models-in-rails">Stackoverflow question</a> (a variation upon the 'Multiple Type' code from the <a href="http://outoftime.github.com/sunspot/rails/docs/index.html" rel="nofollow noreferrer">Sunspot documentation</a>) gave me a solution that I'd think would work, but doesn't.</p>
  
  <p>The multiple method search succeeds, but the facets always turn up null.  My basic approach is to provide a virtual attribute on each model by the same name, :search_class, that is just the model's class name rendered into a string.  I then try and use that as a facet. However, in the view logic the results of the facet (@search.facet(:search_class).rows) is always an empty array, including when @search.results returns many different models in the same query, despite each returned instance having a perfectly accessible Instance.search_class attribute.</p>
  
  <p>I'm using Rails 3.1.0 and sunspot-rails 1.2.1.</p>
  
  <p>What should I do to make this faceting code work?</p>
  
  <p>Controller:</p>
  
  <pre><code>#searches_controller.rb
  class SearchesController &lt; ApplicationController
  
    def show
      @search = search(params[:q])
      @results = @search.results
    end
  
    protected
    def search(q)
      Sunspot.search Foo, Bar, CarlSagan do
        keywords q
        #provide faceting for "search class", a field representing a pretty version of the model name
        facet(:search_class)
        with(:search_class, params[:class]) if params[:class].present?
        paginate(:page =&gt; params[:page], :per_page =&gt; 30)
      end
    end
  
  end
  </code></pre>
  
  <p>Models:</p>
  
  <pre><code>#Foo.rb
  class Foo &lt; ActiveRecord::Base
    searchable do
      text :full_name, :boost =&gt; 5
      text :about, :boost =&gt; 2
      #string for faceting
      string :search_class
    end
  
    #get model name, and, if 2+ words, make pretty
    def search_class
      self.class.name#.underscore.humanize.split(" ").each{|word| word.capitalize!}.join(" ")
    end
  end
  
  #Bar.rb
  class Bar &lt; ActiveRecord::Base
    searchable do
      text :full_name, :boost =&gt; 5
      text :about, :boost =&gt; 2
      #string for faceting
      string :search_class
    end
  
    #get model name, and, if 2+ words, make pretty
    def search_class
      self.class.name.underscore.humanize.split(" ").each{|word| word.capitalize!}.join(" ")
    end
  end
  
  #CarlSagan.rb
  class CarlSagan &lt; ActiveRecord::Base
    searchable do
      text :full_name, :boost =&gt; 5
      text :about, :boost =&gt; 2
      #string for faceting
      string :search_class
    end
  
    #get model name, and, if 2+ words, make pretty
    def search_class
      self.class.name#.underscore.humanize.split(" ").each{|word| word.capitalize!}.join(" ")
    end
  end
  </code></pre>
  
  <p>View:</p>
  
  <pre><code>#searches/show.html.erb
  &lt;div id="search_results"&gt;
  &lt;% if @results.present? %&gt; # If results exist, display them
  
              # If Railscasts-style facets are found, display and allow for filtering through params[:class]
      &lt;% if @search.facet(:search_class).rows.count &gt; 0 %&gt;
          &lt;div id="search_facets"&gt; 
            &lt;h3&gt;Found:&lt;/h3&gt;  
            &lt;ul&gt;  
              &lt;% for row in @search.facet(:search_class).rows %&gt;  
                &lt;li&gt;  
                  &lt;% if params[:class].blank? %&gt;  
                    &lt;%= row.count %&gt;  &lt;%= link_to row.value, :class =&gt; row.value %&gt;
                  &lt;% else %&gt;  
                    &lt;strong&gt;&lt;%= row.value %&gt;&lt;/strong&gt; (&lt;%= link_to "remove", :class =&gt; nil %&gt;)  
                  &lt;% end %&gt;  
                &lt;/li&gt;  
              &lt;% end %&gt;  
            &lt;/ul&gt;  
          &lt;/div&gt;
      &lt;% end %&gt;
  
  
      &lt;% @results.each do |s| %&gt;
          &lt;div id="search_result"&gt;
              &lt;% if s.class.name=="Foo"%&gt;
                  &lt;h5&gt;Foo&lt;/h5&gt;
                  &lt;p&gt;&lt;%= link_to s.name, foo_path(s) %&gt;&lt;/p&gt;
              &lt;% elsif s.class.name=="Bar"%&gt;
                  &lt;h5&gt;Bar&lt;/h5&gt;
                  &lt;p&gt;&lt;%= link_to s.name, bar_path(s) %&gt;&lt;/p&gt;
              &lt;% elsif s.class.name=="CarlSagan"%&gt;
                  &lt;h5&gt;I LOVE YOU CARL SAGAN!&lt;/h5&gt;
                  &lt;p&gt;&lt;%= link_to s.name, carl_sagan_path(s.user) %&gt;&lt;/p&gt;
              &lt;% end %&gt;
          &lt;/div&gt;
      &lt;% end %&gt;
  
  &lt;% else %&gt;
      &lt;p&gt;Your search returned no results.&lt;/p&gt;
      &lt;% end %&gt;
  &lt;/div&gt;
  </code></pre>