Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I DRY up all these calls to render :index?

I have a bunch of controllers with methods that render the index view. This results in me writing render :index at the end of the majority of methods. Here's an example

def index
  @models = Model.find(:all)
end

def new_models
  @models = Model.find_by_new(true)

  render :index
end

def old_models
  @models = Model.find_by_new(false)

  render :index
end

Ideally, I would just move the render code into an after filter, but as the controller makes a call to render before going to the after filter that's not an option.

I have a large number of controllers like this so a solution would remove a lot of repeated code.

This app is currently still Rails 2.3, however, it will be upgraded to Rails 3 in the next month or two. So while I would prefer a technique that works on 2.3, Rails 3 only solutions would still be appreciated.

like image 361
Steven Cummings Avatar asked Jan 31 '11 11:01

Steven Cummings


2 Answers

If you really want to DRY up this action, and if it's very common, then you can do some meta-programming of your own. First create a render_with_index.rb file with this module definition:

module RenderWithIndex
  def self.included klass
    klass.class_eval do
      def self.render_with_index * methods
        methods.each do |method|
          self.class_eval <<-EVAL
            alias :old_method :#{method}

            def #{method}
              old_method
              render :index
            end
          EVAL
        end
      end
    end
  end
end

Then include that module in your controller and define the methods that should render with index (make sure the render_with_index call happens after your method declarations.

include RenderWithIndex

def index
  @models = Model.find(:all)
end

def new_models
  @models = Model.find_by_new(true)
end

def old_models
  @models = Model.find_by_new(false)
end

render_with_index :new_models, :old_models

This module now allows you to render any action with the index template simply by adding it to the render_with_index call.

like image 120
Pan Thomakos Avatar answered Sep 23 '22 20:09

Pan Thomakos


Looks pretty DRY to me. IMHO it's a good habbit to mention which template you are rendering if you don't want to use controller method specific template.

If your render code extends from one-liner into several lines of code, I would DRY them up into separate render method.

like image 43
hade Avatar answered Sep 20 '22 20:09

hade