Synthesis

An easy way to add common finders to your Rails controllers.

Installation

Install the gem directly:

gem sources -a http://gems.github.com (you only have to do this once)
sudo gem install pelargir-finder_filter

Or install the gem in your Rails project:

gem sources -a http://gems.github.com
script/plugin install pelargir-finder_filter

Or clone the project:

git clone git://github.com/pelargir/finder_filter.git

Usage

finder_filter is intended to replace one-off before filters that you might commonly write in your Rails controllers. For example:

class UsersController < ActionController::Base
  before_filter :find_user, :only => [:show, :edit]

  def show
    # do something with @user
  end

  def edit
    # do something with @user
  end

  def find_user
    @user = User.find(params[:id)
  end
end

finder_filter reduces this pattern to a single line:

class UsersController < ActionController::Base
  finder_filter :only => [:show, :edit]

  def show; end
  def edit; end
end

Or, if you want to specify the model to find:

class UsersController < ActionController::Base
  finder_filter :person, :only => [:show, :edit]

  def show; end
  def edit; end
end

To find based on a column other than ID:

finder_filter :user, :by => :name
  # equivalent to:
  #   @user = User.find_by_name(params[:id])

To find based on a param other than ID:

finder_filter :user, :param => :permalink
  # equivalent to:
  #   @user = User.find(params[:permalink])

You can specify that prepend_before_filter is used:

finder_filter :user, :only => [:show, :edit], :prepend => true # generates: # prepend_before_filter :find_user, :only => [:show, :edit]

The standard Rails :only and :except options can also be used:

before_filter :find_user, :only => [:show, :edit]
before_filter :find_user, :except => [:index]

Resource Nesting

If your controller is a nested resource, you might want the find to be performed on the parent model. For example:

class PostsController < ActionController::Base
  before_filter :find_post

  def find_post
    @topic = Topic.find(params[:topic_id])
    @post = @topic.posts.find(params[:id])
  end
end

This can be easily handled using finder_filter:

finder_filter :nested => :topic

Nested resources will only do a find on the parent model if the parent id is supplied. This allows you to handle routing setups like this:

map.resources :posts map.resources :topics do |topic|

topic.resources :posts

end

With this setup, both /posts/1 and /topics/1/posts/2 will be valid URLs, and will do the right thing if you include

finder_filter :nested => :topic

in your Posts controller.

from_param

If you have Michael Bleigh’s from_param (github.com/mbleigh/from_param/tree/master) installed, finder_filter will work transparently with it. This gives you the dual benefit of SEO-friendly URLs and DRY controller code.

Tests

To run the tests, you must have the mocha, test-spec, and sqlite3 gems installed.

rake test

Dependencies

actionpack > 2.0.1

Author

Matthew Bass
  email: pelargir at gmail dot com
  blog: http://matthewbass.com

Contributors

Kevin Smith, Steve Mohapi-Banks