ngauthier / find_or_redirect

Refactor finder code in controllers

This URL has Read+Write access

ngauthier (author)
Fri Oct 23 12:14:06 -0700 2009
commit  601256b3d96c8095de371a248505f3fd6ced456a
tree    5a14568357ad25b40c4937f7eed96bad43d77fe1
parent  1243055bd1b9c282d293fb9e3cecf69d01acf2cc
name age message
file .document Fri Oct 23 11:37:35 -0700 2009 Initial commit to find_or_redirect. [ngauthier]
file .gitignore Fri Oct 23 11:37:35 -0700 2009 Initial commit to find_or_redirect. [ngauthier]
file LICENSE Fri Oct 23 11:37:35 -0700 2009 Initial commit to find_or_redirect. [ngauthier]
file README.rdoc Loading commit data...
file Rakefile Fri Oct 23 11:43:58 -0700 2009 added code from plugin [ngauthier]
file VERSION Fri Oct 23 12:10:47 -0700 2009 Version bump to 0.1.0 [ngauthier]
file find_or_redirect.gemspec Fri Oct 23 12:14:06 -0700 2009 updated gemspec [ngauthier]
directory lib/ Fri Oct 23 11:58:45 -0700 2009 updated code to newer version from other projec... [ngauthier]
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"

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.