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