Search code examples
ruby-on-rails-3reflectionsunspot

Sunspot searches for Rails' Single Table Inheritance


I have a Rails app with the Content model. The Content model has numerous STI children models, such as Announcement, Story, FAQ, etc. I need to be able to query Solr via Sunspot for each of the children independently and as a group.

This is the present implementation of Sunspot search in the Content model. It sets defaults for hidden and published, so only active Content is returned by Solr and accepts a block to allow farther search params:

def self.search_for(&blk)
  search = Sunspot.new_search(Content)
  search.build(&blk)
  search.build do
    with :hidden, false
    with(:published_at).less_than Time.now
  end
  search.execute

  search
 end

This method works perfectly for Content and will return results for Content and all the children Models. I am not particular thrilled with the name of the method, search_for, but can't think of anything better.

I need to be able to search by child Model, i.e. Announcement.search_for(). I do not want to have this method pasted into the ~10 child Models, since the defaults are going to change in the near future. What I would like is have each of the children models inherit this method, but search for the child's class, not Content (e.g. Announcement would search by Sunspot.new_search(Announcement)).

Is there are way to reflect the class of a class method or does this method have to be dynamically generated at runtime to pre-define the calling class?


Solution

  • Pretty easy, just pass the instance type rather than Content. Change first line of the function to:

    search = Sunspot.new_search(self)
    

    Where self will hold Content if you invoke the method by Content.search_for and Announcement if invoked by Announcement.search_for. That's it!