Installing acts_as_ferret with pagination and deploying on Heroku

OMG!

This shouldn’t have been this difficult, but it has because while there are many cool tutorials are out there, they are mostly outdated, and for some reason, the instruction on Heroku was not accessible.

While I picked acts_as_ferret because Heroku supports it, many seemed to prefer Thinking Sphinx. So, if you are not constrained (like me with Heroku), you should try that out too.

1. Install acts_as_ferret

Full instruction is outlined on github, so you should check it out. You can also find the installation instruction and complete list of methods here, too.

While the instruction asks you to put version name, since Heroku only has version 0.4.3 installed, specifying a version will break it.

So, I put the following line in the config/environment.rb.

config.gem ‘acts_as_ferret’

and did

rake gems:install.

2. Install will_paginate

Follow the instruction here to install will_paginate.

3. Modify config/environment.rb

Inside

Rails::Initializer.run do |config|

loop, add the following lines.

config.gem 'will_paginate', :version => '~> 2.3.11', :source => 'http://gemcutter.org'
config.gem 'acts_as_ferret'

And after the loop, add the following two lines. ActsAsFerret.index_dir is very important, since Heroku doesn’t allow write anywhere except tmp directory.

require 'acts_as_ferret'
ActsAsFerret.index_dir = "#{RAILS_ROOT}/tmp/index"
require 'will_paginate'

4. Modify production.rb

This is one change that wasn’t specified anywhere, and took me a while to figure out. I only found it some obscure forum page. Not too obvious. Assuming your Heroku environment is production, put the following lines in the config/environments/production.rb as well.

require 'acts_as_ferret'
ActsAsFerret.index_dir = "#{RAILS_ROOT}/tmp/index"

5. Modify your model

Specify which fields should be searchable in a model. There are ways to search multiple models, and there are many examples you can find online.

I have the following lines in my Post model to search in :title, :content, and :url fields.

acts_as_ferret :fields => [:title, :content, :url]

6. Search action

It’s up to you where you put your search action. I put it in my Post controller, since that’s all I care about. You could possibly have Search controller and search action. You can change per_page parameter to specify how many results are shown per page.

def search
  @query=params[:query]
  @total_hits = Post.total_hits(@query)
  @posts = Post.paginate_with_ferret(@query, :page => params[:page], :per_page => 5)
end

7. In my layouts/application view, I have the following simple form to pass query parameter.

  <% form_tag('/posts/search') do %>
    <%= text_field_tag 'query' %>
    <%= submit_tag 'Search for articles' %>
  <% end %>

8. In search view, I use partial and paginate links to show the results.

Search result for term <%= @query %> resulted in <%= @total_hits %> hits

<%= render :partial => 'post', :collection => @posts %> <%= will_paginate @posts, :params => {:query => @query} %>

That’s it! Once I did it, it was really easy, but I felt very overwhelmed in the beginning.

I hope this saves someone a lot of time. :)

Post to Twitter

4 thoughts on “Installing acts_as_ferret with pagination and deploying on Heroku

  1. You should put
    ActsAsFerret.index_dir = “#{RAILS_ROOT}/tmp/index”
    in initializers/acts_as_ferret.rb

    Then you won’t need any of the require statements since all the gems will already be loaded.

  2. This was a very helpful article, thank you. Though I am finding that even with a single dyno app the /tmp directory is so unstable that the indexes often disappear. How’s your mileage with ferret on heroku lately?

Leave a Reply

Your email address will not be published. Required fields are marked *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax