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.
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
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
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