Fetching contributors…
Cannot retrieve contributors at this time
159 lines (113 sloc) 4.46 KB



How do you integrate Picky in…?


There are basically two basic ways to integrate Picky in Rails:

  • Inside your Rails app
  • With an external server

The advantage of the first setup is that you don't need to manage an external server. However, having a separate search server is much cleaner: You don't need to load the indexes on Rails startup as you just leave the search server running separately.

Inside your Rails app

If you just want a small search engine inside your Rails app, this is the way to go.

In config/initializers/picky.rb, add the following: (lots of comments to help you)

# Set the Picky logger.
Picky.logger =
# Picky.logger =
# Picky.logger =

# Set up an index and store it in a constant.
BooksIndex = :books do
  # Our keys are usually integers.
  key_format :to_i
  # key_format :to_s # From eg. Redis they are strings.
  # key_format ... (whatever method needs to be called on
  # the id of what you are indexing)
  # Some indexing options to start with.
  # Please see:
  # on what the options are.
  indexing removes_characters: /[^a-z0-9\s\/\-\_\:\"\&\.]/i,
           stopwords:          /\b(and|the|of|it|in|for)\b/i,
           splits_text_on:     /[\s\/\-\_\:\"\&\/]/,
           rejects_token_if:   lambda { |token| token.size < 2 }
  # Define categories on your data.
  # They have a lot of options, see:
  category :title
  category :subtitle
  category :author
  category :isbn,
           :partial => # Only full matches

# BookSearch is the search interface
# on the books index. More info here:
BookSearch = BooksIndex

# We are explicitly indexing the book data.
Book.all.each { |book| BooksIndex.add book }

That's already a nice setup. Whenever Rails starts up, this will add all books to the index.

From anywhere (if you have multiple, call Picky::Indexes.index to index all).

Ok, this sets up the index and the indexing. What about the model?

In the model, here app/models/book.rb add this:

# Two callbacks.
after_save    :picky_index
after_destroy :picky_index
# Updates the Picky index.
def picky_index
  if destroyed?
    BooksIndex.remove id
    BooksIndex.replace self

I actually recommend to use after_commit, but it did not work at the time of writing.

Now, in the controller, you need to return some results to the user.

# GET /books/search
def search
  results = query, params[:ids] || 20, params[:offset] || 0

  # Render nicely as a partial.
  results = results.to_hash
  results.extend Picky::Convenience
  results.populate_with Book do |book|
    render_to_string :partial => "book", :object => book

  respond_to do |format|
    format.html do
      render :text => "Book result ids: #{results.ids.to_s}"
    format.json do
      render :text => results.to_json

The first line executes the search using query params. You can try this using curl:


The next few lines use the results as a hash, and populate the results with data loaded from the database, rendering a book partial.

Then, we respond to HTML requests with a simple web page, or respond to JSON requests with the results rendered in JSON.

As you can see, you can do whatever you want with the results. You could use this in an API, or send simple text to the user, or...

TODO Using the Picky client JavaScript.

External Picky server


Advanced Ideas

TODO Reloading indexes live

TODO Prepending the current user to filter

# Prepends the current user filter to
# the current query.
query = "user:#{} #{params[:query]}"



TODO Also mention Padrino.



Ruby Script