Every now and then I have to do something like this in my controllers:

1
2
3
4
5
6
7
8
9
10
11
12
13
 
class SomeItemController < ApplicationController
  ...
 def show
    begin
      @item = SomeItem.find(params[:id])
      # do stuff with item, at least show it!
    rescue
      flash[:notice] = "invalid item #{params[:id]}"
      redirect_to :action => :index
    end
 end
end

This is Plain Wrong. There should be an easier way.. how about if I could do just

1
2
3
4
5
6
7
8
 
class SomeItemController < ApplicationController
  ...
 def show
    given_existing_id do |@item|
      # do stuff with item, at least show it!
    end
end

and if @item can’t be found I want to be automatically redirected to index, maybe with appropriate message in the flash. Can do! So I whipped up the following method and appended it to the application_controller.rb:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 
  def given_existing_id(klass=nil)
    begin
      klass ||= instance_eval(self.class.name.gsub(/Controller$/, '').singularize)
      returning klass.find(params[:id]) do |obj|
        yield obj
      end
    rescue => e
      logger.debug("Error in getting #{klass} item using id #{params[:id]}: #{e.inspect}")
      human_item_name = klass.name.underscore.humanize.downcase
      flash[:notice] = "invalid #{human_item_name} identifier: #{params[:id]}"
      redirect_to :action => :index
      return nil
    end
  end

Certainly you noticed that klass can be supplied instead of using default deduced from the controller, so I can do given_existing_id(MyARModel) do |@model| ... end. It is also easy to have pass custom parameters to find using some sensible defaults etc. Ooh… I just luv R & RoR.

Sorry, comments are closed for this article.