ngauthier / find_or_redirect

Refactor finder code in controllers

This URL has Read+Write access

README.rdoc

find_or_redirect

Find or Redirect helps you refactor out model finding code in your controllers.

Installation

Enable gemcutter, then just:

  gem install find_or_redirect

Usage

This is a common pattern in rails:

  class ModelsController < ApplicationController
    def show
      @model = Model.find(params[:id])
    end

    def destroy
      @model = Model.find(params[:id])
      @model.destroy
    end
  end

Not so dry! Also, this throws exceptions if the model can’t be found. Find or Redirect improves on that by using "find_by_id" and catching a miss with a redirection and friendly flash[:error] message.

It’s like you did this:

  class ModelsController < ApplicationController
    before_filter :find_model
    def show
    end

    def destroy
      @model.destroy
    end

    private

    def find_model
      @model = Model.find_by_id(params[:id])
      unless @model
        redirect_to :action => :index
        flash[:error] = "Invalid model id"
        return false
      end
    end
  end

But it gets repetitive doing that in all your controllers, and it’s certainly not DRY.

So how about:

  class ModelsController
    find_or_redirect :only => [ :show, :destroy ]

    def show
    end

    def destroy
      @model.destroy
    end
  end

The class variable is inferred from the controller name. All options passed to find_or_redirect are automatically passed along to the before_filter created, so you can use :only and :except.

Additional Options

redirect_to

Redirect to a path other than this controller’s index

  find_or_redirect :redirect_to => "root_path"
  find_or_redirect :redirect_to => ":action => :index"
  find_or_redirect :redirect_to => "'http://www.google.com'"

name

Specify the name of the variable to set

  find_or_redirect :name => "something_else"

  def destroy
    @something_else.destroy
  end

finder

Find the model in a different fashion (helpful when the controller name doesn’t match the finder, or if you want to use multiple find_or_redirects)

  class ParentsController
    # this automatically finds the parent
    find_or_redirect
    # now we'll find the child from the parent's children and param
    find_or_redirect(
      :name => "child"
      :finder => "@parent.children.find_by_id(params[:child_id])"
    )
    # and grab the tag the user requested
    find_or_redirect(
      :name => "tag",
      :finder => "Tag.find_by_slug(params[:tag])"
    )

    def update_child_tag
      @child.tag = @tag
      @child.save!
      @parent.last_tag = @tag
      @parent.save!
    end
  end

Note on Patches/Pull Requests

  • Fork the project.
  • Make your feature addition or bug fix.
  • Add tests for it. This is important so I don’t break it in a future version unintentionally.
  • Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but
     bump version in a commit by itself I can ignore when I pull)
    
  • Send me a pull request. Bonus points for topic branches.

Copyright

Copyright © 2009 Nick Gauthier. See LICENSE for details.