Amazon

Sunday, February 17, 2013

Controller#pre_render

As a follow-up to a previous post about Initialize Instance Variables Needed By A View In One Place, here is a more evolved/elegant approach.

First, I override the render method in app/controllers/application_controller.rb:

# override render so we can call pre_render on child classes

def render(*args)
  if self.class.method_defined? :pre_render
    action = args[0].is_a?(Hash) ? (args[0][:action] || action_name) : action_name
    self.pre_render(action.to_sym)
  end
  super
end

Then, I optionally define the pre_render method in my other controllers:

# define this method so that we can initialize the needed instance
# variables the views need all in one place

def pre_render(action)
  case action
  when :edit, :new
    @users = User.all
  when :show
    @subaccounts = @account.subaccounts.order(:name)
  end
end
Conceptually, this is similar to ASP.NET's PreRender() event handler.

Thursday, February 14, 2013

Linux Myth

I remember one of the knocks against Windows was how often it needs to be patched and rebooted, and that Linux/Unix does not. Well, I am here to say that is a myth. I manage a couple of Ubuntu boxes, and the rate at which patches and reboots come in are just as frequent, if not more so, than the Windows ones I manage.

Wednesday, February 6, 2013

Initialize Instance Variables Needed By A View In One Place

In Rails, should Controller#create fail, the pre-generated code will call render :action => "new". But all too often rendering the new view requires other instance variables to be assigned, which don't get assigned in this execution path if I place the initialization code in the Controller#new method.

I have been frustrated by the lack of a good way to handle it. At first I looked into the presenter pattern, but did not come up with anything that I liked.

Then, I came across this idea, which at first glance, seems to work well. My main goal is to have a good place to initialize the needed instance variables needed by the view only once, and overriding #render seems like a good way to go.

Your thoughts?
# Override this method so that we can initialize the needed
# instance variables the view needs all in one place

def render(*args)
  action = args[0][:action] || action_name
  case action
  when "new"
    @accounts = Account.order(:name)
    ...
  end
end