Rails 3 upgrade part 3: Code fixes, views, and forms

This is part 3 of my Rails 2 to Rails 3 upgrade experience. Part 1 is about the initial code upgrade and getting the application to boot while part 2 deals with routes. While Part 2 is mainly about routes, getting it work involved changes in other parts of the code which I’ll share this time. So while you are updating your routes, you may need to check this post in between changes.

Update ApplicationController

After regenerating your application with rails (i.e. rails new appname -d dbadapter), your ApplicationController would look like this:

  class ApplicationController < ActionController::Base

There’s no need to panic because rails:upgrade:backup made a copy of the controller to application_controller.rb.rails2.

If you have a lot of helper modules, you’ll most likely have this code in your Rails 2 ApplicationController:

helper :all

If you encounter a missing method error while monkey clicking your application, you probably forgot to update your Rails 3 ApplicationController.

Update ApplicationHelper

The ApplicationHelper module was also modified by the rails upgrde. So don’t forget to update this, too.

RAILS_* constants are deprecated is not entirely true

When you run rails:upgrade:check, it will list items you need to update including deprecated code. There is no need to change these as the word ‘deprecated’ means but I encountered several “can’t convert nil into String” errors.

  rake rails:upgrade:check
  (in /mnt/hgfs/greg-mini/dev/projects/propsify)
  Deprecated constant(s)
  Constants like RAILS_ENV, RAILS_ROOT, and RAILS_DEFAULT_LOGGER are now deprecated.
  More information: http://litanyagainstfear.com/blog/2010/02/03/the-rails-module/
  The culprits: 

The weird part is some constants are just doing fine. In any case, here are the conversion:

  RAILS_ROOT  -> Rails.root
  RAILS_ENV -> Rails.env
  RAILS_DEFAULT_LOGGER -> Rails.logger

You can also check your environment the Ruby way:

  # before
  if RAILS_ENV == 'production'
  # Rails 3
  if Rails.env.production?

Output strings are automatically escaped

We should all be rejoicing that Rails is now serious about XSS protection except now your pages have become ugly with all those HTML tags. For example the code below will not give you a clickable link.

  - signup = link_to('create one here', signup_path)
  = "If you do not have an account, #{signup}."

To fix this, use the raw() helper.

  = raw "If you do not have an account, #{signup}."

Too bad for me, I got tons of views that were coded like this.

Check for ‘concat’

A popular technique to simplify your view code is to use content blocks. You create a helper that takes a block and wraps it in some HTML tags. A simple implementation would look like this:

  module LayoutHelper
    def main_column(options={}, &amp;block)
      # calls column()
    def column(options={}, &amp;block)
      # concat is not needed in Rails 3
      concat content_tag(:div, capture(&amp;block), options)
  # in your view
  - main_column do
    = render 'form'

This works fine in Rails 2 but in Rails 3 the block gets outputted twice. concat is the way to output text in a non-output block (i.e. <% %> in erb) but it seems like erb blocks in Rails 3 do not need concat.

Helpers with blocks

Before Rails 3, form_for or fields_for use non-output syntax; it means no equals sign.

  # erb
  <% form_for @offer do |f| %>
    # ...
  <% end %>
  # haml
  - form_for @offer do |f|
    # ...

In Rails 3, it should now be written as an output block.

  # erb
  <%= form_for @offer do |f| %>
    # ...
  <% end %>
  # haml
  = form_for @offer do |f|
    = f.fields_for :items do |ff|
      # ...

The rule is if the method is expected to return a string, it should use the output syntax. If it just buffering the returned string like content_for, it should NOT have the equals sign.


One thought on “Rails 3 upgrade part 3: Code fixes, views, and forms

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s