How Do I Scope Enums in Rails Using Sunspot?

北城余情 提交于 2019-12-22 18:19:49

问题


I am trying to use Sunspot (Rails Solr gem) to scope results using an enum I have declared in my model. The relevant portion of my model looks like this:

searchable do
  text :tag_list
  boolean :approved
  integer :perspective
  time :created_at
end

enum perspective: [ :not_applicable, :front, :side_front, :side, :side_back, :back, :above, :below ]

My search block in my controller looks like this:

def index
  //skip scoping if perspective is nil
  params[:perspective] ||= []

  @search = Upload.search do
    with :approved, true
    with :perspective, params[:perspective]
    fulltext params[:tag]
    fulltext params[:search] do
      minimum_match 1
    end
    paginate page: params[:page], per_page: 30
  end
    @uploads = @search.results
    @query = params[:search]
end

And the link I'm using to collect the params looks like this:

<%= link_to upload.perspective.humanize, search_index_path(perspective: Upload.perspectives[upload.perspective]), class: "perspective" %>

Basically I'm trying to set this up so that it returns the results of any combination of all of these criteria after scoping by approved. I've got it working with the text based search criteria, but the scoping by perspective is not working. The search just returns all the results for 0 and none for any other value. Am I missing something about how Sunspot/Solr works with enums? When I do a query such as Upload.where(perspective: 1) I get the proper results, so I'm not sure why this isn't working.

Thanks in advance.


回答1:


I finally got this one solved. The issue was that although Rails stores the enum value as an integer in the database, it does not retrieve that integer when you call the enum attribute (in this case @upload.perspective). This returns a string corresponding to the name of the value instead ("front", "side", etc. in this case). The problem with this is that in my searchable block I was declaring the perspective field as an integer.

The solution:

A method in the model which grabs the enum id integer rather than the name:

def perspective_id
  Upload.perspectives[self.perspective]
end

Modifying the searchable block:

searchable do
  text :tag_list
  boolean :approved
  integer :perspective_id
  time :created_at
end

And the search block in the controller:

def index
  #if no perspective, set to empty hash so solr skips
  params[:perspective] ||= []
  @search = Upload.search do
    with :approved, true
    with :perspective_id, params[:perspective]
    fulltext params[:tag]
    fulltext params[:search] do
      minimum_match 1
    end
    paginate page: params[:page], per_page: 30
  end
    @uploads = @search.results
    @query = params[:search]
end



回答2:


Rails enums are quite a dark magic. Remember it's all integers in the database.

I'm betting your params[:perspective] is a string(like 'front') and not an underlying integer. Calling Model.perspectives[:front] on the other hand will return proper integer value. Try converting it to underlying value using

Model.perspectives[params[:perspective]]

before passing to search method.

More info here: rails docs




回答3:


You don't have to write those extra coding actually. Just do it like this:

searchable do
  #...
  string :perspective
  #...
end

#while searching
with :perspective, 'above'


来源:https://stackoverflow.com/questions/29161105/how-do-i-scope-enums-in-rails-using-sunspot

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!