I have a Topic that has_many comments. In the search results only want Topics to show up, but I want them to include the text of the comments that they have when they are indexed. To do this I''ve added a :comments_text field for acts_as_ferret and the comments_text method gathers the text from all comments up into a string that can be indexed. The trick is that when comments are added, updated, or deleted the Topic needs to be updated in the ferret index, and I''m not sure what the best way to enforce that is. I''ve included my current code to do this, which seems to work, but I''d like to know if there is a better way to maintain this dependency then what I''m doing. In particular am I using appropriate callback methods in Comment to trigger the updates on Topic (ie. after_create, after_update, after_destroy). And to make the destroy case work I''m needing to call unless each.frozen? in the comments_text method... is that the right thing to do? Thanks. Here''s my existing code: class Topic < ActiveRecord::Base acts_as_ferret :store_class_name => true, :fields => { :comments_text => { :store => :yes } } has_many :comments, :as => :commentable, :dependent => :destroy def comments_text result = "" for each in comments unless each.frozen? result << " " result << each.subject result << " " result << each.body end end result end end class Comment < ActiveRecord::Base belongs_to :commentable, :polymorphic => true def after_create commentable.ferret_update end def after_update commentable.ferret_update end def after_destroy commentable.ferret_update end end -- Posted via http://www.ruby-forum.com/.
On Thu, Apr 05, 2007 at 05:44:53PM +0200, Jesse Grosjean wrote:> I have a Topic that has_many comments. In the search results only want > Topics to show up, but I want them to include the text of the comments > that they have when they are indexed. To do this I''ve added a > :comments_text field for acts_as_ferret and the comments_text method > gathers the text from all comments up into a string that can be indexed. > > The trick is that when comments are added, updated, or deleted the Topic > needs to be updated in the ferret index, and I''m not sure what the best > way to enforce that is. I''ve included my current code to do this, which > seems to work, but I''d like to know if there is a better way to maintain > this dependency then what I''m doing. In particular am I using > appropriate callback methods in Comment to trigger the updates on Topic > (ie. after_create, after_update, after_destroy). And to make the destroy > case work I''m needing to call unless each.frozen? in the comments_text > method... is that the right thing to do?Well, calling frozen? is not an extraordinary clean solution (in terms of code readability - one does not easily understand from reading the code why it is done), but probably the most efficient one. Doing a commentable.reload before calling ferret_update should work without the check for frozen?, because the newly loaded collection will not include the deleted comment any more. So, in the spirit of ''premature optimization is the root of all evil'' you would probably do that instead and do the frozen? optimization only once the need arises (i.e. things get slow because of the additional DB usage). Or just write a comment explaining the frozen? check... Jens -- Jens Kr?mer webit! Gesellschaft f?r neue Medien mbH Schnorrstra?e 76 | 01069 Dresden Telefon +49 351 46766-0 | Telefax +49 351 46766-66 kraemer at webit.de | www.webit.de Amtsgericht Dresden | HRB 15422 GF Sven Haubold, Hagen Malessa
Jens, Thanks for your help and for your work on this cool plugin. I didn''t know about the reload option, that works great. I was just going to complain that multi_search didn''t return the results in the proper score order (it was returning them sorted by Class, and then store), but I just check out trunk and it works great there. So thanks again. Jesse -- Posted via http://www.ruby-forum.com/.