What's new in acts_as_ferret Part 2 - Lazy loading
Besides the integrated DRb server, Lazy loading of AR objects is the other big new feature in acts_as_ferret.
Until now, aaf only used the Ferret index for the retrieval of primary keys of records matching a query. These then were used to get the relevant objects out of the database via ActiveRecord. But Ferret can also store and retrieve the contents of any other field you put into the index.
This especially comes in handy for all kinds of live searches. Just store the relevant fields directly in the index and get them back from your search without a single database query. Unfortunately you’d now have to deal with two different kinds of result objects in your views - those from the index and those from your db. Not so with acts_as_ferret.
Acts_as_ferret makes the whole thing completely transparent - you can use your aaf query result as if it were a normal AR model instance. Behind the scenes aaf will only fetch the record from your databse when it needs to, that is when you ask for an attribute that could not be loaded from the index.
Say you have an Article model with the following declaration:
class Article
acts_as_ferret :fields => { :title => { :store => :yes },
:excerpt => { :store => :yes },
:content => {} }
end
Pay attention to the :store => :yes
option for the title
and excerpt
fields - that’s how you tell aaf to store the title and excerpt of articles directly inside the Ferret index. Now the only thing that is left is telling find_by_contents to not prefetch all the AR records from the db:
# search articles, fetch all fields stored in the index, but don't hit the database
results = Article.find_by_contents(query_string, :lazy => true)
like above, but only fetch the title fields of results
results = Article.find_by_contents(query_string, :lazy => [ :title ]) </code>
In your view display the search results as usual (assuming you have a _result.rhtml
partial for rendering the result list inside an ul
):
<li><%= link_to h(result.title), result_path(result) %><br /><%= result.excerpt %></li>
As long as you don’t try to access any of the non-stored fields like content
ore excerpt
(if using the second find_by_contents
example), no database query will be made to load the article.
Comments
michael
is it possible to index only a series of objects with a special attribute into ferret vi acts_as_ferret.
let's say i have some deleted objects in the database with a date set in the deleted_at atrribute that should not get indexed. i did not figure out where to set a filter that only objects with deleted_at = null get indexed.
thanks in advance
michael
Jens
michael