Best way to maintain dynamic fields?

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

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

On Thu, Apr 05, 2007 at 05:44:53PM +0200, Jesse G. wrote:

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
[email protected] | www.webit.de

Amtsgericht Dresden | HRB 15422
GF Sven Haubold, Hagen Malessa