Find Resource

This Rails plugin creates a finder method in your controller, based on the controller name. For instance, if your controller was called PostsController, a find_post method would be created. A before_filter is also added for the show, edit, update and destroy actions.

Current Version: 0.2

Please see the CHANGELOG.

Installation

  • Via "svn export": script/plugin install http://svn.turnipspatch.com/public/find_resource/
  • Via "svn:externals": script/plugin install -x http://svn.turnipspatch.com/public/find_resource/
  • With Piston: piston import http://svn.turnipspatch.com/public/find_resource/ vendor/plugins/find_resource

Dungeddit?

It's quite hard to describe this plugin briefly, so let me present the reasoning behind it.

This is your basic RESTful PostsController:

class PostsController < ApplicationController
  def index
    # code
  end

  def show
    @post = Post.find(params[:id])
    # code
  end

  def new
    # code
  end

  def create
    # code
  end

  def edit
    @post = Post.find(params[:id])
    # code
  end

  def update
    @post = Post.find(params[:id])
    # code
  end

  def destroy
    @post = Post.find(params[:id])
    # code
  end
end

The line @post = Post.find(params[:id]) gets repeated four times, which is not very DRY. So we refactor that line into a private find_post method which gets called with a before_filter:

class PostsController < ApplicationController
  before_filter :find_post, :only => %w(show edit update destroy)

  def index
    # code
  end

  def show
    # code
  end

  def new
    # code
  end

  def create
    # code
  end

  def edit
    # code
  end

  def update
    # code
  end

  def destroy
    # code
  end

  private

  def find_post
    @post = Post.find(params[:id])
  end
end

This is better, but when you have a PostsController, UsersController and CommentsController, each with a finder method like this, there is still duplication. This is where my plugin comes in. When create_resource_finder is called, if one doesn't already exist, it creates a find_foo method based on the controller's name. So the PostsController gets a find_post method identical to the one above. It also adds the before_filter as seen above. The refactored controller, using this plugin, becomes:

class PostsController < ApplicationController
  create_resource_finder

  def index
    # code
  end

  def show
    # code
  end

  def new
    # code
  end

  def create
    # code
  end

  def edit
    # code
  end

  def update
    # code
  end

  def destroy
    # code
  end
end

Magic!

Sometimes you might want more from your finder method. The configuration options explained below will probably satisfy your requirements, but if not just create the method manually and create_resource_finder will still add the before_filter for you.

Configuration

create_resource_finder options

You can pass options to create_resource_finder. All options not recognised by the plugin will be passed on to find(). You can use this to specify something like :include => :comments.

:model

The :model option takes a string which specifies the model to create a finder for. Usually this is implied by the name of your controller anyway, but it was suggested that there may be occasions where the model name is not related to the controller name.

Example:

class BlogController
  create_resource_finder :model => "Article"
end

:context

You may want to do your finding within the context of a collection of models. This might be for security; current_user.articles.find() ensures you will only ever get the articles belonging to that user. You can specify a context as a string and it will be evaluated later.

Example:

class ArticlesController
  create_resource_finder :context => "current_user.articles"
end

Actions to be filtered

The before_filter this plugin adds gets called for the show, edit, update and destroy actions, by default. You can change this by putting the following into your environment.rb:

ActionController::FindResource::ResourceFinder.filter_actions = %w(foo bar baz)