<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
  <title>opensoul.org - Using shared indexes with acts_as_ferret Changes</title>
  <id>tag:opensoul.org,2009:/2008/4/29/using-shared-indexes-with-acts_as_ferret/changes</id>
  <generator version="0.8.0" uri="http://mephistoblog.com">Mephisto Drax</generator>
  <link href="http://opensoul.org/2008/4/29/using-shared-indexes-with-acts_as_ferret/changes.xml" rel="self" type="application/atom+xml"/>
  <link href="/2008/4/29/using-shared-indexes-with-acts_as_ferret" rel="alternate" type="text/html"/>
  <updated>2008-05-12T02:29:00Z</updated>
  <entry xml:base="http://opensoul.org/">
    <author>
      <name>brandon</name>
    </author>
    <id>tag:opensoul.org,2008-05-12:432:6</id>
    <updated>2008-05-12T02:29:00Z</updated>
    <link href="http://opensoul.org/2009/10/23/using-shared-indexes-with-acts_as_ferret" rel="alternate" type="text/html"/>
    <title>Using shared indexes with acts_as_ferret</title>
<content type="html">&lt;p&gt;So by now we all know how to do wicked-cool search with &lt;a href=&quot;http://projects.jkraemer.net/acts_as_ferret/&quot;&gt;acts_as_ferret&lt;/a&gt;. (If not, the &lt;a href=&quot;http://www.railsenvy.com/2007/2/19/acts-as-ferret-tutorial&quot;&gt;RailsEnvy guys can lend a hand&lt;/a&gt;, but the tutorial is a little outdated for the latest trunk version of acts_as_ferret. Just replace &lt;code&gt;#find_by_contents&lt;/code&gt; with &lt;code&gt;#find_with_ferret&lt;/code&gt; and you should be good.)&lt;/p&gt;


	&lt;p&gt;But searching a single model is &lt;em&gt;so&lt;/em&gt; last year. All the cool kids are getting promiscuous with their searches and involving multiple models. Fortunately for us, recent revisions of &lt;code&gt;acts_as_ferret&lt;/code&gt; makes this easy-peasy.&lt;/p&gt;


	&lt;p&gt;The key to making this happen is a shared index: we want all of our models indexed in one place so ferret only has to do one search. We can do it without a shared index, but then we have to do a ferret search and thus a &lt;span class=&quot;caps&quot;&gt;SQL&lt;/span&gt; select for each model. Plus, if we want your search results interspersed and sorted by rank, we have to have a shared index.&lt;/p&gt;


	&lt;h3&gt;Enough chit-chat, show us how!&lt;/h3&gt;


	&lt;p&gt;Ok, I&#8217;m getting to it. Grab the latest version of acts as ferret from trunk:&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;script/plugin install svn://projects.jkraemer.net/acts_as_ferret/trunk/plugin/acts_as_ferret&lt;/code&gt;&lt;/pre&gt;


	&lt;p&gt;Now, instead of defining &lt;code&gt;acts_as_ferret&lt;/code&gt; in our models, we define them all in &lt;code&gt;config/aaf.rb&lt;/code&gt;&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;ActsAsFerret::define_index('shared',
 :models =&amp;gt; {
   Person  =&amp;gt; {:fields =&amp;gt; [:first_name, :last_name, :phone, :bio]},
   Company =&amp;gt; {:fields =&amp;gt; [:name, :description]},
   Post    =&amp;gt; {:fields =&amp;gt; [:title, :body]}
 },
 :ferret   =&amp;gt; {
   :default_fields =&amp;gt; [:first_name, :last_name, :phone, :bio, :name, :description, :title, :body]
 }
)&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;This defines a new index, called &#8220;shared&#8221;, and then defines the &lt;code&gt;acts_as_ferret&lt;/code&gt; configuration for each model.&lt;/p&gt;


	&lt;p&gt;Now for the fun part: searching our shiny new index.&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;def search
  @results = ActsAsFerret.find(params[:q], 'shared')
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;This will give us one array with any models that matched the search query, ordered by rank. And for those times when we only want to search one model, we can still do that.&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;def search
  @people = Person.find_with_ferret(params[:q])
end&lt;/code&gt;&lt;/pre&gt;

	&lt;h3&gt;How do we display the results?&lt;/h3&gt;


	&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: Sorry, originally I had an example using resources, but that doesn&#8217;t work as-is;  I was doing something a little different in the app that this example came from.&lt;/p&gt;


	&lt;p&gt;To display our search results, we just render a partial for each model in the result:&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;erb&quot;&gt;&amp;lt;% @results.each do |result| %&amp;gt;
  &amp;lt;%= render :partial =&amp;gt; &amp;quot;search/#{dom_class(result)}&amp;quot; %&amp;gt;
&amp;lt;% end %&amp;gt;&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;This will just look for a partial for each model (like &lt;code&gt;search/_person.html.erb&lt;/code&gt;).&lt;/p&gt;


	&lt;p&gt;So there you have it. Now you too can have promiscuous searching.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: I&#8217;ve put together an &lt;a href=&quot;http://opensoul.org/assets/2008/5/12/ferret-example_1.zip&quot;&gt;example rails app&lt;/a&gt; that uses the shared index. It uses sqlite and has some date pre-populated. Start up &lt;code&gt;script/server&lt;/code&gt; and do a search for &#8220;John&#8221;.&lt;/p&gt;</content>  </entry>
  <entry xml:base="http://opensoul.org/">
    <author>
      <name>brandon</name>
    </author>
    <id>tag:opensoul.org,2008-05-12:431:5</id>
    <updated>2008-05-12T02:27:32Z</updated>
    <link href="http://opensoul.org/2009/10/23/using-shared-indexes-with-acts_as_ferret" rel="alternate" type="text/html"/>
    <title>Using shared indexes with acts_as_ferret</title>
<content type="html">&lt;p&gt;So by now we all know how to do wicked-cool search with &lt;a href=&quot;http://projects.jkraemer.net/acts_as_ferret/&quot;&gt;acts_as_ferret&lt;/a&gt;. (If not, the &lt;a href=&quot;http://www.railsenvy.com/2007/2/19/acts-as-ferret-tutorial&quot;&gt;RailsEnvy guys can lend a hand&lt;/a&gt;, but the tutorial is a little outdated for the latest trunk version of acts_as_ferret. Just replace &lt;code&gt;#find_by_contents&lt;/code&gt; with &lt;code&gt;#find_with_ferret&lt;/code&gt; and you should be good.)&lt;/p&gt;


	&lt;p&gt;But searching a single model is &lt;em&gt;so&lt;/em&gt; last year. All the cool kids are getting promiscuous with their searches and involving multiple models. Fortunately for us, recent revisions of &lt;code&gt;acts_as_ferret&lt;/code&gt; makes this easy-peasy.&lt;/p&gt;


	&lt;p&gt;The key to making this happen is a shared index: we want all of our models indexed in one place so ferret only has to do one search. We can do it without a shared index, but then we have to do a ferret search and thus a &lt;span class=&quot;caps&quot;&gt;SQL&lt;/span&gt; select for each model. Plus, if we want your search results interspersed and sorted by rank, we have to have a shared index.&lt;/p&gt;


	&lt;h3&gt;Enough chit-chat, show us how!&lt;/h3&gt;


	&lt;p&gt;Ok, I&#8217;m getting to it. Grab the latest version of acts as ferret from trunk:&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;script/plugin install svn://projects.jkraemer.net/acts_as_ferret/trunk/plugin/acts_as_ferret&lt;/code&gt;&lt;/pre&gt;


	&lt;p&gt;Now, instead of defining &lt;code&gt;acts_as_ferret&lt;/code&gt; in our models, we define them all in &lt;code&gt;config/aaf.rb&lt;/code&gt;&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;ActsAsFerret::define_index('shared',
 :models =&amp;gt; {
   Person  =&amp;gt; {:fields =&amp;gt; [:first_name, :last_name, :phone, :bio]},
   Company =&amp;gt; {:fields =&amp;gt; [:name, :description]},
   Post    =&amp;gt; {:fields =&amp;gt; [:title, :body]}
 },
 :ferret   =&amp;gt; {
   :default_fields =&amp;gt; [:first_name, :last_name, :phone, :bio, :name, :description, :title, :body]
 }
)&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;This defines a new index, called &#8220;shared&#8221;, and then defines the &lt;code&gt;acts_as_ferret&lt;/code&gt; configuration for each model.&lt;/p&gt;


	&lt;p&gt;&lt;del&gt;To get this to load, and to make it so we don&#8217;t lose our configuration in development when the models reload, we need to add a bit in &lt;code&gt;config/environment.rb&lt;/code&gt;. I&#8217;ve &lt;a href=&quot;http://projects.jkraemer.net/acts_as_ferret/ticket/215&quot;&gt;submitted a patch&lt;/a&gt; so we won&#8217;t have to do this, but for now:&lt;/del&gt; &lt;strong&gt;Update&lt;/strong&gt;: my patch was accepted, so you can skip this.&lt;/p&gt;


	&lt;p&gt;&lt;del&gt;&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;config.after_initialize do
  ActsAsFerret.initialize
end&lt;/code&gt;&lt;/pre&gt;&lt;/del&gt;&lt;/p&gt;


	&lt;p&gt;Now for the fun part: searching our shiny new index.&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;def search
  @results = ActsAsFerret.find(params[:q], 'shared')
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;This will give us one array with any models that matched the search query, ordered by rank. And for those times when we only want to search one model, we can still do that.&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;def search
  @people = Person.find_with_ferret(params[:q])
end&lt;/code&gt;&lt;/pre&gt;

	&lt;h3&gt;How do we display the results?&lt;/h3&gt;


	&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: Sorry, originally I had an example using resources, but that doesn&#8217;t work as-is;  I was doing something a little different in the app that this example came from.&lt;/p&gt;


	&lt;p&gt;To display our search results, we just render a partial for each model in the result:&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;erb&quot;&gt;&amp;lt;% @results.each do |result| %&amp;gt;
  &amp;lt;%= render :partial =&amp;gt; &amp;quot;search/#{dom_class(result)}&amp;quot; %&amp;gt;
&amp;lt;% end %&amp;gt;&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;This will just look for a partial for each model (like &lt;code&gt;search/_person.html.erb&lt;/code&gt;).&lt;/p&gt;


	&lt;p&gt;So there you have it. Now you too can have promiscuous searching.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;: I&#8217;ve put together an &lt;a href=&quot;http://opensoul.org/assets/2008/5/12/ferret-example_1.zip&quot;&gt;example rails app&lt;/a&gt; that uses the shared index. It uses sqlite and has some date pre-populated. Start up &lt;code&gt;script/server&lt;/code&gt; and do a search for &#8220;John&#8221;.&lt;/p&gt;</content>  </entry>
  <entry xml:base="http://opensoul.org/">
    <author>
      <name>brandon</name>
    </author>
    <id>tag:opensoul.org,2008-04-30:429:4</id>
    <published>2008-04-29T14:51:00Z</published>
    <updated>2008-04-30T14:20:30Z</updated>
    <link href="http://opensoul.org/2008/4/29/using-shared-indexes-with-acts_as_ferret" rel="alternate" type="text/html"/>
    <title>Using shared indexes with acts_as_ferret</title>
<content type="html">&lt;p&gt;So by now we all know how to do wicked-cool search with &lt;a href=&quot;http://projects.jkraemer.net/acts_as_ferret/&quot;&gt;acts_as_ferret&lt;/a&gt;. (If not, the &lt;a href=&quot;http://www.railsenvy.com/2007/2/19/acts-as-ferret-tutorial&quot;&gt;RailsEnvy guys can lend a hand&lt;/a&gt;, but the tutorial is a little outdated for the latest trunk version of acts_as_ferret. Just replace &lt;code&gt;#find_by_contents&lt;/code&gt; with &lt;code&gt;#find_with_ferret&lt;/code&gt; and you should be good.)&lt;/p&gt;


	&lt;p&gt;But searching a single model is &lt;em&gt;so&lt;/em&gt; last year. All the cool kids are getting promiscuous with their searches and involving multiple models. Fortunately for us, recent revisions of &lt;code&gt;acts_as_ferret&lt;/code&gt; makes this easy-peasy.&lt;/p&gt;


	&lt;p&gt;The key to making this happen is a shared index: we want all of our models indexed in one place so ferret only has to do one search. We can do it without a shared index, but then we have to do a ferret search and thus a &lt;span class=&quot;caps&quot;&gt;SQL&lt;/span&gt; select for each model. Plus, if we want your search results interspersed and sorted by rank, we have to have a shared index.&lt;/p&gt;


	&lt;h3&gt;Enough chit-chat, show us how!&lt;/h3&gt;


	&lt;p&gt;Ok, I&#8217;m getting to it. Grab the latest version of acts as ferret from trunk:&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;script/plugin install svn://projects.jkraemer.net/acts_as_ferret/trunk/plugin/acts_as_ferret&lt;/code&gt;&lt;/pre&gt;


	&lt;p&gt;Now, instead of defining &lt;code&gt;acts_as_ferret&lt;/code&gt; in our models, we define them all in &lt;code&gt;config/aaf.rb&lt;/code&gt;&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;ActsAsFerret::define_index('shared',
 :models =&amp;gt; {
   Person  =&amp;gt; {:fields =&amp;gt; [:first_name, :last_name, :phone, :bio]},
   Company =&amp;gt; {:fields =&amp;gt; [:name, :description]},
   Post    =&amp;gt; {:fields =&amp;gt; [:title, :body]}
 },
 :ferret   =&amp;gt; {
   :default_fields =&amp;gt; [:first_name, :last_name, :phone, :bio, :name, :description, :title, :body]
 }
)&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;This defines a new index, called &#8220;shared&#8221;, and then defines the &lt;code&gt;acts_as_ferret&lt;/code&gt; configuration for each model.&lt;/p&gt;


	&lt;p&gt;&lt;del&gt;To get this to load, and to make it so we don&#8217;t lose our configuration in development when the models reload, we need to add a bit in &lt;code&gt;config/environment.rb&lt;/code&gt;. I&#8217;ve &lt;a href=&quot;http://projects.jkraemer.net/acts_as_ferret/ticket/215&quot;&gt;submitted a patch&lt;/a&gt; so we won&#8217;t have to do this, but for now:&lt;/del&gt; &lt;strong&gt;Update&lt;/strong&gt;: my patch was accepted, so you can skip this.&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;config.after_initialize do
  ActsAsFerret.initialize
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Now for the fun part: searching our shiny new index.&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;def search
  @results = ActsAsFerret.find(params[:q], 'shared')
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;This will give us one array with any models that matched the search query, ordered by rank. And for those times when we only want to search one model, we can still do that.&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;def search
  @people = Person.find_with_ferret(params[:q])
end&lt;/code&gt;&lt;/pre&gt;

	&lt;h3&gt;How do we display the results?&lt;/h3&gt;


	&lt;p&gt;If we&#8217;re using &lt;code&gt;map.resources&lt;/code&gt; in our routes, it&#8217;s really easy:&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;erb&quot;&gt;&amp;lt;%= render :partial =&amp;gt; @results %&amp;gt;&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;This is going to look for a partial for each record based on the model name. So for &lt;code&gt;Person&lt;/code&gt;, it would look for &lt;code&gt;people/_person.html.erb&lt;/code&gt;.  If we&#8217;re not using &lt;code&gt;map.resources&lt;/code&gt;, or want to display our search results differently, we could just do something like this:&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;erb&quot;&gt;&amp;lt;% @results.each do |result| %&amp;gt;
  &amp;lt;%= render :partial =&amp;gt; &amp;quot;search/#{dom_class(result)}&amp;quot; %&amp;gt;
&amp;lt;% end %&amp;gt;&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;This will just look for a partial for each model (like &lt;code&gt;search/_person.html.erb&lt;/code&gt;).&lt;/p&gt;


	&lt;p&gt;So there you have it. Now you too can have promiscuous searching.&lt;/p&gt;</content>  </entry>
  <entry xml:base="http://opensoul.org/">
    <author>
      <name>brandon</name>
    </author>
    <id>tag:opensoul.org,2008-04-29:428:3</id>
    <published>2008-04-29T14:51:00Z</published>
    <updated>2008-04-29T14:55:56Z</updated>
    <link href="http://opensoul.org/2008/4/29/using-shared-indexes-with-acts_as_ferret" rel="alternate" type="text/html"/>
    <title>Using shared indexes with acts_as_ferret</title>
<content type="html">&lt;p&gt;So by now we all know how to do wicked-cool search with &lt;a href=&quot;http://projects.jkraemer.net/acts_as_ferret/&quot;&gt;acts_as_ferret&lt;/a&gt;. (If not, the &lt;a href=&quot;http://www.railsenvy.com/2007/2/19/acts-as-ferret-tutorial&quot;&gt;RailsEnvy guys can lend a hand&lt;/a&gt;, but the tutorial is a little outdated for the latest trunk version of acts_as_ferret. Just replace &lt;code&gt;#find_by_contents&lt;/code&gt; with &lt;code&gt;#find_with_ferret&lt;/code&gt; and you should be good.)&lt;/p&gt;


	&lt;p&gt;But searching a single model is &lt;em&gt;so&lt;/em&gt; last year. All the cool kids are getting promiscuous with their searches and involving multiple models. Fortunately for us, recent revisions of &lt;code&gt;acts_as_ferret&lt;/code&gt; makes this easy-peasy.&lt;/p&gt;


	&lt;p&gt;The key to making this happen is a shared index: we want all of our models indexed in one place so ferret only has to do one search. We can do it without a shared index, but then we have to do a ferret search and thus a &lt;span class=&quot;caps&quot;&gt;SQL&lt;/span&gt; select for each model. Plus, if we want your search results interspersed and sorted by rank, we have to have a shared index.&lt;/p&gt;


	&lt;h3&gt;Enough chit-chat, show us how!&lt;/h3&gt;


	&lt;p&gt;Ok, I&#8217;m getting to it. Grab the latest version of acts as ferret from trunk:&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;script/plugin install svn://projects.jkraemer.net/acts_as_ferret/trunk/plugin/acts_as_ferret&lt;/code&gt;&lt;/pre&gt;


	&lt;p&gt;Now, instead of defining &lt;code&gt;acts_as_ferret&lt;/code&gt; in our models, we define them all in &lt;code&gt;config/aaf.rb&lt;/code&gt;&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;ActsAsFerret::define_index('shared',
 :models =&amp;gt; {
   Person  =&amp;gt; {:fields =&amp;gt; [:first_name, :last_name, :phone, :bio]},
   Company =&amp;gt; {:fields =&amp;gt; [:name, :description]},
   Post    =&amp;gt; {:fields =&amp;gt; [:title, :body]}
 },
 :ferret   =&amp;gt; {
   :default_fields =&amp;gt; [:first_name, :last_name, :phone, :bio, :name, :description, :title, :body]
 }
)&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;This defines a new index, called &#8220;shared&#8221;, and then defines the &lt;code&gt;acts_as_ferret&lt;/code&gt; configuration for each model.&lt;/p&gt;


	&lt;p&gt;To get this to load, and to make it so we don&#8217;t lose our configuration in development when the models reload, we need to add a bit in &lt;code&gt;config/environment.rb&lt;/code&gt;. I&#8217;ve &lt;a href=&quot;http://projects.jkraemer.net/acts_as_ferret/ticket/215&quot;&gt;submitted a patch&lt;/a&gt; so we won&#8217;t have to do this, but for now:&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;config.after_initialize do
  ActsAsFerret.initialize
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;Now for the fun part: searching our shiny new index.&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;def search
  @results = ActsAsFerret.find(params[:q], 'shared')
end&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;This will give us one array with any models that matched the search query, ordered by rank. And for those times when we only want to search one model, we can still do that.&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;def search
  @people = Person.find_with_ferret(params[:q])
end&lt;/code&gt;&lt;/pre&gt;

	&lt;h3&gt;How do we display the results?&lt;/h3&gt;


	&lt;p&gt;If we&#8217;re using &lt;code&gt;map.resources&lt;/code&gt; in our routes, it&#8217;s really easy:&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;erb&quot;&gt;&amp;lt;%= render :partial =&amp;gt; @results %&amp;gt;&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;This is going to look for a partial for each record based on the model name. So for &lt;code&gt;Person&lt;/code&gt;, it would look for &lt;code&gt;people/_person.html.erb&lt;/code&gt;.  If we&#8217;re not using &lt;code&gt;map.resources&lt;/code&gt;, or want to display our search results differently, we could just do something like this:&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;erb&quot;&gt;&amp;lt;% @results.each do |result| %&amp;gt;
  &amp;lt;%= render :partial =&amp;gt; &amp;quot;search/#{dom_class(result)}&amp;quot; %&amp;gt;
&amp;lt;% end %&amp;gt;&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;This will just look for a partial for each model (like &lt;code&gt;search/_person.html.erb&lt;/code&gt;).&lt;/p&gt;


	&lt;p&gt;So there you have it. Now you too can have promiscuous searching.&lt;/p&gt;</content>  </entry>
  <entry xml:base="http://opensoul.org/">
    <author>
      <name>brandon</name>
    </author>
    <id>tag:opensoul.org,2008-04-29:427:2</id>
    <published>2008-04-29T14:51:00Z</published>
    <updated>2008-04-29T14:55:05Z</updated>
    <link href="http://opensoul.org/2008/4/29/using-shared-indexes-with-acts_as_ferret" rel="alternate" type="text/html"/>
    <title>Using shared indexes with acts_as_ferret</title>
<content type="html">&lt;p&gt;So by now we all know how to do wicked-cool search with &lt;a href=&quot;http://projects.jkraemer.net/acts_as_ferret/&quot;&gt;acts_as_ferret&lt;/a&gt;. (If not, the &lt;a href=&quot;http://www.railsenvy.com/2007/2/19/acts-as-ferret-tutorial&quot;&gt;RailsEnvy guys can lend a hand&lt;/a&gt;, but the tutorial is a little outdated for the latest trunk version of acts_as_ferret. Just replace &lt;code&gt;#find_by_contents&lt;/code&gt; with &lt;code&gt;#find_with_ferret&lt;/code&gt; and you should be good.)&lt;/p&gt;


	&lt;p&gt;But searching a single model is &lt;em&gt;so&lt;/em&gt; last year. All the cool kids are getting promiscuous with their searches and involving multiple models. Fortunately for us, recent revisions of &lt;code&gt;acts_as_ferret&lt;/code&gt; makes this easy-peasy.&lt;/p&gt;


	&lt;p&gt;The key to making this happen is a shared index: we want all of our models indexed in one place so ferret only has to do one search. We can do it without a shared index, but then we have to do a ferret search and thus a &lt;span class=&quot;caps&quot;&gt;SQL&lt;/span&gt; select for each model. Plus, if we want your search results interspersed and sorted by rank, we have to have a shared index.&lt;/p&gt;


	&lt;h3&gt;Enough chit-chat, show us how!&lt;/h3&gt;


	&lt;p&gt;Ok, I&#8217;m getting to it. Grab the latest version of acts as ferret from trunk:&lt;/p&gt;


	&lt;pre&gt;&lt;code&gt;script/plugin install svn://projects.jkraemer.net/acts_as_ferret/trunk/plugin/acts_as_ferret&lt;/code&gt;&lt;/pre&gt;


	&lt;p&gt;Now, instead of defining &lt;code&gt;acts_as_ferret&lt;/code&gt; in our models, we define them all in &lt;code&gt;config/aaf.rb&lt;/code&gt;&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;ActsAsFerret::define_index('shared',
 :models =&amp;gt; {
   Person  =&amp;gt; {:fields =&amp;gt; [:first_name, :last_name, :phone, :bio]},
   Company =&amp;gt; {:fields =&amp;gt; [:name, :description]},
   Post    =&amp;gt; {:fields =&amp;gt; [:title, :body]}
 },
 :ferret   =&amp;gt; {
   :default_fields =&amp;gt; [:first_name, :last_name, :phone, :bio, :name, :description, :title, :body]
 }
)&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;This defines a new index, called &#8220;shared&#8221;, and then defines the &lt;code&gt;acts_as_ferret&lt;/code&gt; configuration for each model.&lt;/p&gt;


	&lt;p&gt;To get this to load, and to make it so we don&#8217;t lose our configuration in development when the models reload, we need to add a bit in &lt;code&gt;config/environment.rb&lt;/code&gt;. I&#8217;ve &lt;a href=&quot;http://projects.jkraemer.net/acts_as_ferret/ticket/215&quot;&gt;submitted a patch&lt;/a&gt; so we won&#8217;t have to do this, but for now:&lt;/p&gt;


	&lt;p&gt;This will give us one array with any models that matched the search query, ordered by rank. And for those times when we only want to search one model, we can still do that.&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;def search
  @people = Person.find_with_ferret(params[:q])
end&lt;/code&gt;&lt;/pre&gt;

	&lt;h3&gt;How do we display the results?&lt;/h3&gt;


	&lt;p&gt;If we&#8217;re using &lt;code&gt;map.resources&lt;/code&gt; in our routes, it&#8217;s really easy:&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;erb&quot;&gt;&amp;lt;%= render :partial =&amp;gt; @results %&amp;gt;&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;This is going to look for a partial for each record based on the model name. So for &lt;code&gt;Person&lt;/code&gt;, it would look for &lt;code&gt;people/_person.html.erb&lt;/code&gt;.  If we&#8217;re not using &lt;code&gt;map.resources&lt;/code&gt;, or want to display our search results differently, we could just do something like this:&lt;/p&gt;


&lt;pre&gt;&lt;code class=&quot;erb&quot;&gt;&amp;lt;% @results.each do |result| %&amp;gt;
  &amp;lt;%= render :partial =&amp;gt; &amp;quot;search/#{dom_class(result)}&amp;quot; %&amp;gt;
&amp;lt;% end %&amp;gt;&lt;/code&gt;&lt;/pre&gt;

	&lt;p&gt;This will just look for a partial for each model (like &lt;code&gt;search/_person.html.erb&lt;/code&gt;).&lt;/p&gt;


	&lt;p&gt;So there you have it. Now you too can have promiscuous searching.&lt;/p&gt;</content>  </entry>
</feed>
