Reputation: 838
I am using a few persisted Tire models in my Rails app. Searching has been working fine, using Tire.search ['index1','index2'], :load => true do ...
But I now made a new index and model, and I get the following error when trying to include it in the search and access its results:
undefined method `detect' for #<AuthoredHistory:0x000001013d6a88>
I see it's coming from Tire::Results::Collection#results, down at the last line:
@response['hits']['hits'].map { |item| records[item['_type']].detect { |record| record.id.to_s == item['_id'].to_s } }
For some reason records[item['_type']]
returns a Tire::Results::Collection object for my other models, but with the new class it returns an AuthoredHistory object, which is my actual model class. I saw something about this on the gem's github page, but I am not doing anything with Tire.configuration.wrapper. I am including Persistence, Search, and Callbacks modules in all indexed models.
Am I missing something? Can someone please point me in the right direction? (karmi, I'm hoping you can save me here!)
[UPDATE]
Now I'm getting somewhere... an error was occurring when only 1 result from a particular index is returned with the results. If there are 2 or more results from an index, it wraps it in Tire::Results::Collection. Now to find a hack...
[UPDATE again]
Hacky solution found! Look below for the answer...
Upvotes: 1
Views: 834
Reputation: 838
I found a hack that I believe works... not a pretty one, but that's the nature of the hack. If there is only ONE result for a particular model, the records do not return a Tire::Results::Collection
object but rather just an object of the actual model, which fails on detect
. So, I must check if we have a Collection or not, and if not, simply wrap it in an array. It seems to work for now, hopefully there are no ill effects down the road...
Here is the hack... this replaces the problematic line that I posted in the question:
@response['hits']['hits'].map do |item|
collection = records[item['_type']].is_a?(Tire::Results::Collection) ?
records[item['_type']] :
[records[item['_type']]]
collection.detect { |record| record.id.to_s == item['_id'].to_s }
end
ALSO! I had done a hack before to account for when the search results as a whole only returned one item. I had to insert this line right before the same problematic line above:
return [records[@response['hits']['hits'].first['_type']]] if @response['hits']['hits'].size == 1
Upvotes: 0
Reputation: 107728
I think you're missing the curly brace for the map before the detect. It should be this:
@response['hits']['hits'].map { |item| records[item['_type']] }.detect { |record| record.id.to_s == item['_id'].to_s }
I don't know the codebase well enough to know this for sure, but I think records[item['_type']]
is going to be returning one of those AuthoredHistory
objects, which don't have the detect
method on them.
The detect
method is used in Enumerable
collections in Ruby, and that's kind of object that map
returns (it'll return an Array
) object. Therefore, the curly brace was in the wrong position.
Upvotes: 1