I have been trying to use multi_search to search accross multiple associated models, but I have had no luck at all. I have scoured the net and this forum for all similar posts, but none of them contain enough code for me to get it to work. I am successfully able to search individual models, and then display the results without a problem. I have the following 2 models, Product and Component. The Product model has_many Components, and the Component model belongs_to Product. Could anyone provide an example of how they would search the Product model for a query term, which will then return not only the Products that match the query, but the Components (related to the Products) as well. I would really appreciate a "back-to-basics" example, as I think I have confused myself completely in my attempts. Thanks. -- Posted via http://www.ruby-forum.com/.
Graham,
First, to do multi_search make sure to declare :store_class_name => true
in both the Product and Component files in order to do multi_search.
class Product < ActiveRecord::Base
acts_as_ferret :store_class_name => true
...
end
class Component < ActiveRecord::Base
acts_as_ferret :store_class_name => true
...
end
Next, if you want to retrieve products based on in its components, you
have to index your product based on the appropriate component values:
class Product < ActiveRecord::Base
acts_as_ferret :store_class_name => true,
:fields => [ ''field1'',
''field2'',
:index_components
]
...
end
def index_components
@index = Array.new
for component in self.components
@index << component.field1.to_s
@index << component.field2.to_s
end
@index.join(" ")
end
Basically, acts_as_ferret will index any model based on the text your
throw at it. Now, something like Product.find_by_contents("query
term")
should retrieve products based on text in all of its component fields.
Finally, you can do multi_search via:
@results = Product.multi_search("query term", [Component])
This search will retrieve both Product and Component models in the array
@results. Now that you have both, you have to check what the class type
is in your view files before displaying the search results:
<% @results.each do |result| %>
<% if result.class == Product %>
# code to display your Product here
<% else %>
# code to display your Component here
<% end %>
<% end %>
I wasn''t able to go into all the details here, but I hope this helps.
Rami
Graham wrote:> I have been trying to use multi_search to search accross multiple
> associated models, but I have had no luck at all. I have scoured the net
> and this forum for all similar posts, but none of them contain enough
> code for me to get it to work.
>
> I am successfully able to search individual models, and then display the
> results without a problem.
>
> I have the following 2 models, Product and Component. The Product model
> has_many Components, and the Component model belongs_to Product.
>
> Could anyone provide an example of how they would search the Product
> model for a query term, which will then return not only the Products
> that match the query, but the Components (related to the Products) as
> well.
>
> I would really appreciate a "back-to-basics" example, as I think
I have
> confused myself completely in my attempts.
>
> Thanks.
--
Posted via http://www.ruby-forum.com/.
Hi Rami,
Thanks for the reply... I am still not able to get it to work though. I
am getting the same error that I was getting during my own attempts
(well at one stage anyway!) although when I try in the console, I get a
different error.
Here is my code...
#### Code ####
class Product < ActiveRecord::Base
has_many :Components
acts_as_ferret( :store_class_name => true, :fields => [
:index_components, ''name'', ''description'' ] )
def index_components
@index = Array.new
for component in self.components
@index << component.name.to_s
@index << component.description.to_s
end
@index.join(" ")
end
end
class Component < ActiveRecord::Base
belongs_to :Product
acts_as_ferret( :store_class_name => true, :fields => [
''name'',
''description'' ] )
end
class SearchController < ApplicationController
def search
@query = params[:search] || ''''
unless @query.blank?
@results = Product.multi_seach( @query, [ Component ] )
end
....
end
#### End Code ####
The error I am getting in the browser is, "undefined method
`multi_seach'' for Product:Class" and the error I am getting the
console
if I try it manually is, "TypeError: nil is not a symbol".
This made me think that I need to include the acts_as_ferret plugin
somewhere in my code, but then why would find_by_contents work? Anyway,
at least you have confirmed that my code is correct in my models and
controller. Any ideas on these errors?
Regards,
Graham
Rami wrote:> Graham,
>
> First, to do multi_search make sure to declare :store_class_name => true
> in both the Product and Component files in order to do multi_search.
>
> class Product < ActiveRecord::Base
> acts_as_ferret :store_class_name => true
> ...
> end
>
> class Component < ActiveRecord::Base
> acts_as_ferret :store_class_name => true
> ...
> end
>
> Next, if you want to retrieve products based on in its components, you
> have to index your product based on the appropriate component values:
>
> class Product < ActiveRecord::Base
> acts_as_ferret :store_class_name => true,
> :fields => [ ''field1'',
> ''field2'',
> :index_components
> ]
> ...
> end
>
> def index_components
> @index = Array.new
> for component in self.components
> @index << component.field1.to_s
> @index << component.field2.to_s
> end
> @index.join(" ")
> end
>
> Basically, acts_as_ferret will index any model based on the text your
> throw at it. Now, something like Product.find_by_contents("query
term")
> should retrieve products based on text in all of its component fields.
>
> Finally, you can do multi_search via:
>
> @results = Product.multi_search("query term", [Component])
>
> This search will retrieve both Product and Component models in the array
> @results. Now that you have both, you have to check what the class type
> is in your view files before displaying the search results:
>
> <% @results.each do |result| %>
> <% if result.class == Product %>
> # code to display your Product here
> <% else %>
> # code to display your Component here
> <% end %>
> <% end %>
>
> I wasn''t able to go into all the details here, but I hope this
helps.
>
> Rami
>
> Graham wrote:
>> I have been trying to use multi_search to search accross multiple
>> associated models, but I have had no luck at all. I have scoured the
net
>> and this forum for all similar posts, but none of them contain enough
>> code for me to get it to work.
>>
>> I am successfully able to search individual models, and then display
the
>> results without a problem.
>>
>> I have the following 2 models, Product and Component. The Product model
>> has_many Components, and the Component model belongs_to Product.
>>
>> Could anyone provide an example of how they would search the Product
>> model for a query term, which will then return not only the Products
>> that match the query, but the Components (related to the Products) as
>> well.
>>
>> I would really appreciate a "back-to-basics" example, as I
think I have
>> confused myself completely in my attempts.
>>
>> Thanks.
--
Posted via http://www.ruby-forum.com/.
I have just noticed a glaring typo! In the SearchController, I am using multi_seach but I should be using multi_search (with the R!) so now I am getting the "Nil is not a Symbol" error in the browser too. -- Posted via http://www.ruby-forum.com/.
Ok... I seem to have got rid of the "nil is not a Symbol" error by enclosing my @query in "" as below... @results = Product.multi_search( "@query", [ Component ] ) The problem now is that it is returning no results. In my development log, there isn''t even a SQL query like when I use find_by_contents. Graham wrote:> I have just noticed a glaring typo! In the SearchController, I am using > multi_seach but I should be using multi_search (with the R!) so now I am > getting the "Nil is not a Symbol" error in the browser too.-- Posted via http://www.ruby-forum.com/.
> The problem now is that it is returning no results. In my development > log, there isn''t even a SQL query like when I use find_by_contents.Can you check that your product and component models are being properly indexed by aaf (using the development log)? Its possible you may have a nil component model which aaf is trying to index. Try adding "unless self.components.nil?" to your code: def index_components unless self.components.nil? @index = Array.new for component in self.components @index << component.name.to_s @index << component.description.to_s end @index.join(" ") end end Also, I would delete your old index folder and have aaf re-create it next time you startup your app. Rami Graham wrote:> Ok... I seem to have got rid of the "nil is not a Symbol" error by > enclosing my @query in "" as below... > > @results = Product.multi_search( "@query", [ Component ] ) > > The problem now is that it is returning no results. In my development > log, there isn''t even a SQL query like when I use find_by_contents. > > Graham wrote: >> I have just noticed a glaring typo! In the SearchController, I am using >> multi_seach but I should be using multi_search (with the R!) so now I am >> getting the "Nil is not a Symbol" error in the browser too.-- Posted via http://www.ruby-forum.com/.
Hi Rami, Thanks for the help so far... I deleted the index directories, and then restarted the webserver. The folders, products & components, have been created in the index folder, but it doesn''t seem to actually be indexing anything. Also, I now no longer get no results, but I have the old "You have a nil object when you didn''t expect it!" error. This is so frustrating :) find_by_contents works fine everytime... Also, the indexes seem to be created as well when using this method. Can we recap quickly? I installed Ferret using gems. I then installed the AAF plugin using the trunk SVN. Should I be doing anything else at this point in terms of the installation? I then made my models & controller look like the code in this post. First, I used find_by_contents to test it all out, and was able to get proper results back. I then changed the search method to multi_search and nothing is returned. Sorry about this... but I am sure I am doing everything I should be doing. Regards, Graham Rami wrote:>> The problem now is that it is returning no results. In my development >> log, there isn''t even a SQL query like when I use find_by_contents. > > Can you check that your product and component models are being properly > indexed by aaf (using the development log)? Its possible you may have a > nil component model which aaf is trying to index. Try adding "unless > self.components.nil?" to your code: > > def index_components > unless self.components.nil? > @index = Array.new > for component in self.components > @index << component.name.to_s > @index << component.description.to_s > end > @index.join(" ") > end > end > > Also, I would delete your old index folder and have aaf re-create it > next time you startup your app. > > Rami-- Posted via http://www.ruby-forum.com/.
On Sun, 2006-08-20 at 14:37 +0200, Graham wrote:> Ok... I seem to have got rid of the "nil is not a Symbol" error by > enclosing my @query in "" as below... > > @results = Product.multi_search( "@query", [ Component ] )"@query" doesn''t use the query variable. Are you sure @query contains something? Maybe you want params[:query] or something of the sort. Pedro.
No it definitely contains my search string... I set a breakpoint and then inspected it in the console. I think it is because the indexes are not being built. I have been working on getting Ferret to work without AAF and I am at last getting somewhere. Pedro =?ISO-8859-1?Q?C=F4rte-Real?= wrote:> On Sun, 2006-08-20 at 14:37 +0200, Graham wrote: >> Ok... I seem to have got rid of the "nil is not a Symbol" error by >> enclosing my @query in "" as below... >> >> @results = Product.multi_search( "@query", [ Component ] ) > > "@query" doesn''t use the query variable. Are you sure @query contains > something? Maybe you want params[:query] or something of the sort. > > Pedro.-- Posted via http://www.ruby-forum.com/.
On Mon, 2006-08-21 at 15:53 +0200, Guest wrote:> No it definitely contains my search string... I set a breakpoint and > then inspected it in the console.@query might contain your search string but "@query" doesn''t. For example: irb(main):001:0> @query = ''foo'' => "foo" irb(main):002:0> @query => "foo" irb(main):003:0> "@query" => "@query" Putting quotes around it makes it just another string and doesn''t use the variable at all. To do that you''d have to do: irb(main):004:0> "#{@query}" => "foo" which is pretty redundant although it will guard against @query being nil: irb(main):005:0> "#{@bar}" => "" but then you can just do: irb(main):007:0> @bar||'''' => "" Hope this helps. Pedro.
Yes, I see what you mean... I had taken the "" off before I abandoned AAF, but it still made no difference. I have now successfully indexed all my models and can search them all relative to Product - using Ferret on its own. AAF just did not work for me. -- Posted via http://www.ruby-forum.com/.
On 8/22/06, Graham <gmwebs at googlemail.com> wrote:> Yes, I see what you mean... I had taken the "" off before I abandoned > AAF, but it still made no difference. > > I have now successfully indexed all my models and can search them all > relative to Product - using Ferret on its own. AAF just did not work for > me.Hi Graham, Just a quick pointer. If you happen to upgrade to Ferret 0.10.0 (it''ll require some work since the latest version has many non-backwards compatible changes) then you should use a MultiReader supplied to a Searcher rather than a MultiSearcher. It''s much more efficient. reader = IndexReader.new([reader1, reader2, reader3]) searcher = Searcher.new(reader) Cheers, Dave