Skip to main content

Installing acts_as_ferret with pagination and deploying on Heroku

·465 words·3 mins
Author
Yang Chung

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. :)