This Week in Rails 3.0

Now that Rails 2.3 has hit the release candidate phase, some of the development effort is turning to Rails 3.0. With that activity heating up, it’s time to start keeping you all informed as to happenings on the 3.0 version of the Rails source. I’ll still be posting separate “This Week in Edge Rails” information focused on Rails 2.3, so you can keep straight which changes are ready now and which still lie in the relatively distant future.

The Vision

The Rails 3 vision is based on the announcement that was made in December: we’re bringing in the key ideas from Merb to Rails, including:

  • A more modular Rails core, so you can run applications with less than the full Rails stack
  • Performance optimizations
  • Framework agnosticism with sensible defaults
  • A tested and documented API for extensions

Rails 3 promises to substantially advance the state of the art in Ruby web frameworks, while still providing migration paths from Rails 2.x and Merb 1.×.

The Source Code

The Rails 3.0 branch in the main Rails project on GitHub is the place to be to see what’s going on:

git clone git://
git checkout 3-0-unstable

As the branch name might tell you, this is still a fairly experimental place to be: you probably don’t want to roll this out for production applications just yet. But it is tested code (and it’s using continuous integration to stay that way), and it already includes substantial changes from Rails 2.x thanks to the efforts of Yehuda Katz, Joshua Peek, and others. The changes so far are focused on cleaning up and improving Rails internals, rather than on adding new features.

Action Dispatch

Action Dispatch is a new Rails component which lives in Action Pack (along with Action Controller and Action View). Action Dispatch is responsible for all the processing involved with dispatching requests: request and response handling, HTTP status codes, file uploads, URL and parameter parsing, session storage, and so on.

Action View Reorganization

There are substantial changes in the Action View internals. The overall goal was to clean up a bunch of special cases and extra hooks that had built up over the years, and to leave all callers into Action View using a single unified entry point. The code cleanup has been coupled with some rearrangement of the Action View source to make it easier to find bits of functionality. This was a substantial effort; if you’re interested in a detailed look at the refactoring, you can read up on it at Yehuda’s blog

Callback Optimizations

A new method of handling callbacks removes the need for iterating through the callback list at runtime, and provides a substantial speed improvement in this area of the code. Though this is a micro-optimization that may not have much effect by itself, the hope is that by carefully optimizing as many hot spots as possible we can get a visible overall speedup in page creation and delivery – which, after all, is the point of a web framework.

What’s Next?

Obviously, there’s a long distance between where we are today and the Rails 3.0 vision. We’re fortunate to have an excellent team of core programmers devoting substantial time to making that journey. The interim goal is still to have a beta version of Rails 3.0 out in time for RailsConf in May. You can help in the same ways as with earlier versions of Rails: download the source, start testing it with your applications, and submit your own ideas and patches to the Rails Lighthouse. Rails has been a joint effort of thousands of developers over the years, and Rails 3.0 will be no different in that regard.

Rails Guides Gets a Facelift

There’s a brand new version of Rails coming, as you already know. What better time for a new version of some of the Rails documentation? So the Rails Guides team is pleased to announce a refresh of the Ruby on Rails Guides site, just in time for the Rails 2.3 release.

The most obvious change you’ll see is a new look, thanks to some awesome design work from Jason Zimdars. But the visual refresh isn’t all that’s going on here. We’ve also been working to update the Guides for Rails 2.3, as well as to add new guides to the list.

And there’s good news if you want to get involved too. Behind the scenes, Tore and Pratik switched our markup engine from AsciiDoc to Textile. This makes the Guides easier to write and edit and easier to build into a Rails project. If you’ve got some spare time to help out, join us in the #docrails room on, and help make the Rails Guides into a great resource in time for the 2.3 release.

Calling All Rails-Savvy Designers

One thing that has been a continuing challenge for many Rails developers is finding a good designer to work with. There are certainly plenty of fantastic designers out there, but it’s often difficult to find one who is comfortable working directly in a Rails project.

In an effort to help ease this challenge, and at the behest of some interested developers and designers, the Rails Activists have set up a group for Ruby Graphics Designers. The idea is to have a place for communication: a spot where designers can ask questions about git or erb, or where developers can try to find a designer to work with.

Of course, a group without participation is nothing to crow about. If you’re a developer – or especially if you’re a designer who works with Rails – we’d love to have your participation. If you’re interested in the visual design and information architecture of Rails applications, c’mon by and say hi! And if you have other ideas about how we can encourage closer collaboration between the Rails community and the design community, we’d love to hear them.

Rails 2.3.0 RC1: Templates, Engines, Rack, Metal, much more!

Rails 2.3 is almost ready for release, but this package is so stock full of amazing new stuff that we’re making dutifully sure that everything works right before we call it official.

So please help us do thorough testing of this release candidate. Lots of the underpinnings changed. Especially the move to Rack. So we need solid testing and will probably have a slightly longer than average release candidate phase to account for that.

But boy will it be worth it. This is one of the most substantial upgrades to Rails in a very long time. A brief rundown of the top hitters:

  • Templates: Allows your new skeleton Rails application to be built your way with your default stack of gems, configs, and more.
  • Engines: Share reusable application pieces complete with routes that Just Work, models, view paths, and the works.
  • Rack: Rails now runs on Rack which gives you access to all the middleware goodness.
  • Metal: Write super fast pieces of optimized logic that routes around Action Controller.
  • Nested forms: Deal with complex forms so much easier.

And that’s just the tip of the iceberg. We’ve put together a complete guide for the Rails 2.3 release notes with much more information.

You can install the release candidate with:

gem install rails --source

Enjoy, report the bugs, and let’s get Rails 2.3 final out the door soon.

This Week in Edge Rails

January 24, 2009 – January 30, 2009

This week we saw 35 commits in edge Rails – though many are bug fixes and minor things. Here’s one more preview of some of the recent and significant changes.

Localized Views

Rails can now provide localized views, depending on the locale that you have set. For example, suppose you have a Posts controller with a show action. By default, this will render app/views/posts/show.html.erb. But if you set I18n.locale = :da, it will render app/views/posts/show.da.html.erb. If the localized template isn’t present, the undecorated version will be used. Rails also includes I18n#available_locales and I18n::SimpleBackend#available_locales, which return an array of the translations that are available in the current Rails project.


Reconnecting MySQL Connections

MySQL supports a reconnect flag in its connections – if set to true, then the client will try reconnecting to the server before giving up in case of a lost connection. You can now set reconnect = true for your MySQL connections in database.yml to get this behavior from a Rails application. The default is false, so the behavior of existing applications doesn’t change.


Easier Testing for JDBC

To make life easier for anyone using Rails on JRuby, Active Record now includes test tasks for a bunch of database accessible via JDBC: Derby, H2, hsqldb, MySQL, PostgreSQL, and sqlite3 (the latter three are also available through non-JDBC connections, as you know). You need to have the database, the activerecord-jdbc-adapter gem installed, and the specific activerecord-jdbcdatabase-gem for the database you’re testing. Then you can run tests like this: jruby -S rake test_jdbcmysql (with similar tests for the other adapters, of course).


HTTP Digest Authentication Support

This one first appeared a couple of weeks ago, but was reverted due to some problems with the initial implementation. Fortunately, the problems were resolved, and Rails 2.3 will ship with built-in support for HTTP digest authentication. Ryan Daigle published some sample code.


grouped_options_for_select Helper Method

Action View already has a bunch of helpers to aid in generating select controls, but now there’s one more: grouped_options_for_select. This one accepts an array or hash of strings, and converts them into a string of option tags wrapped with optgroup tags. For example:

   ["Baseball Cap","Cowboy Hat"]]], 
   "Cowboy Hat", "Choose a product...")


 <option value="">Choose a product...</option>
 <optgroup label="Hats">
   <option value="Baseball Cap">Baseball Cap</option>
   <option selected="selected" value="Cowboy Hat">
     Cowboy Hat


Ruby / Rails Conferences

When the economy hits a downturn this typically has an immediate effect on tech conferences. Many tech conferences cannot run successfully without sponsorships, and with companies becoming more conservative with spending the marketing budget is usually the first item to get cut.

So yet another way you can help Ruby and Rails Activism is by attending (supporting) a conference. Below you’ll find conferences coming up in the next 6 months. If you think I’ve missed one, or if the information is incorrect, please post a comment.

Acts as Conference

February 6-7 – Acts As Conference in Orlando, Florida

Cost: $125


February 19-21 – RubyRx in Durham, North Carolina

Cost: $550

MountainWest RubyConf 2009

March 12-14 – MountainWest RubyConf 2009 in Salt Lake City, Utah

Cost: $100

Scotland on Rails

March 26-28 – Scotland on Rails in Scotland, United Kingdom

Cost: £150

Locos X Rails

April 3-4 – Locos X Rails in Buenos Aires, Argentina

Cost: ?

LA Ruby Conf 2009

April 4 – LA Ruby Conf 2009 in Los Angeles, California

Cost: $75

Golden Gate Ruby Conference

April 17-18 – Golden Gate Ruby Conference in San Francisco, California

Cost: ?

RailsConf 2009

May 4-7 – RailsConf 2009 in Las Vegas, Nevada

Cost: $695

Euruko 2009

May 9-10 – Euruko 2009 in Barcelona, Spain

Cost: 30 Euro

RailsCamp 5

May 15-18 – RailsCamp 5 in Brisbane, Australia

Cost: $120 AUD


Since I initially wrote up this post, there have been several more events I’ve been made aware of (from the comments):

It’s pretty cool to see more RubyCamps. I’m a big fan of BarCamp type events where you keep admission free. Perhaps in this financial climate these types of events will prosper more then they normally do. Feel free to bug me if you want help putting one of these together or need help with publicity.

Autoloading ActiveResource schemas

I just committed a little feature during our Rails core hackfest in Chicago: [Autoloading ActiveResource schemas]( Note: this is in my personal fork that's up to date with the rails repo, and will probably be merged in for Rails 2.3. I've received some requests for this from people having problems using `Lighthouse::Ticket` records with `form_for` helpers in their Rails apps. The idea is that resources can automatically load the starting XML just once, like the way ActiveRecord loads the schema from the database. This is already part of the current Rails scaffolding:

class PostsController < ApplicationController
  def new
    @post =
    respond_to do |format|
      format.html # new.html.erb
      format.xml { render :xml => @post }
There is one problem though, this probably won't work for protected or nested actions. Ideally a Rails app will set a top level route for the resource, and disable any before filters if `request.format.xml?` is true.

map.route 'tickets/new.:format', :controller => 'tickets', :action => 'new'
You can get around this by modifying the `#schema` hash directly, or calling `#reset_schema` with your own prefixes. Here's a sample using the [Lighthouse API lib](

Lighthouse.account = 'entp'
Lighthouse.token = 'monkey'
Lighthouse::Ticket.reset_schema :project_id => 1

# or, use a well known public project
Lighthouse.account = 'rails'
Lighthouse::Ticket.reset_schema :project_id => 8994 # => #<Lighthouse::Ticket:0x1707898 @attributes={"permalink"=>nil, "updated_at"=>nil, "number"=>nil, "title"=>nil, "creator_id"=>nil, "tag"=>nil, "attachments_count"=>0, "priority"=>0, "closed"=>false, "assigned_user_id"=>nil, "user_id"=>nil, "created_at"=>nil, "state"=>nil, "milestone_id"=>nil}, @prefix_options={:project_id=>8994}>

Visualizing the Rails commit history

Ilya Grigorik wrote up a post on [generating a code swarm visualization from git repositories]( He wrote [gitter]( to feed the git commit info for the Rails repository and feed it to [code swarm](
Ruby on Rails from Ilya Grigorik on Vimeo. It's worth checking out the HD version. Git was introduced around 4:40 :)

Nested Model Forms

The most popular request on our new Feedback site was for the ability to easily manage multiple models in a single form. Thankfully Eloy Duran has a patch that does just this. But before we roll it into rails 2.3 we want to get some more feedback from you guys. Eloy's written this brief introduction to the patch, so take a look, and add any feedback you have to the lighthouse ticket.

In Rails it has always been a little tricky to create a single form for both a model and its associations. Last summer, the :accessible option was committed as a first stab at a unified solution for dealing with nested models. However, this feature was pulled before the 2.2 release because it only supported nested models during object creation.

The resulting discussion on the core mailing list and our need for mass assignment have resulted in this patch for ticket #1202 which is now up for scrutinizing.

Since this is a rather large patch we would like to invite you to give it a try. Please report any issues or give feedback about the patch in general. We are especially interested to know how the provided solutions work for applications that allow deletion of nested records through their forms.

Below I'll give a quick tour on what the patch does and how to use it so you have no excuse not to give it a try.

Get the patch

Start by creating a new application:

$ mkdir -p nested-models/vendor
$ cd nested-models/vendor

Vendor your Rails branch with the nested models patches:

$ git clone git://
$ cd rails
$ git checkout origin/normalized_nested_attributes
$ cd ../..
$ ruby vendor/rails/railties/bin/rails .

An example of nested assignment

Suppose you have a project model with associated tasks:

class Project < ActiveRecord::Base
  has_many :tasks

  validates_presence_of :name
class Task < ActiveRecord::Base
  belongs_to :project

  validates_presence_of :name

Now consider the following form which allows you to simultaneously create (or edit) a project and its tasks:

    <label for="project_name">Project:</label>
    <input type="text" name="project_name" />

    <label for="task_name_1">Task:</label>
    <input type="text" name="task_name_1" />
    <label for="task_delete_1">Remove:</label>
    <input type="checkbox" name="task_delete_1" />

    <label for="task_name_2">Task:</label>
    <input type="text" name="task_name_2" />
    <label for="task_delete_2">Remove:</label>
    <input type="checkbox" name="task_delete_2" />

Before the patch

Before this patch you would have to write a template like this:

<% form_for @project do |project_form| %>
    <%= project_form.label :name, 'Project name:' %>
    <%= project_form.text_field :name %>

  <% @project.tasks.each do |task| %>
    <% new_or_existing = task.new_record? ? 'new' : 'existing' %> 
    <% prefix = "project[#{new_or_existing}_task_attributes][]" %> 
    <% fields_for prefix, task do |task_form| %>
          <%= task_form.label :name, 'Task:' %>
          <%= task_form.text_field :name %>

        <% unless task.new_record? %>
            <%= task_form.label :_delete, 'Remove:' %>
            <%= task_form.check_box :_delete %>
        <% end %>
    <% end %>
  <% end %>

  <%= project_form.submit %>
<% end %>

The controller is pretty much your average restful controller. The Project model however needs to know how to handle the nested attributes:

class Project < ActiveRecord::Base
  after_update :save_tasks

  def new_task_attributes=(task_attributes)
    task_attributes.each do |attributes|

  def existing_task_attributes=(task_attributes)
    tasks.reject(&:new_record?).each do |task|
      attributes = task_attributes[]
      if attributes['_delete'] == '1'
        task.attributes = attributes


  def save_tasks
    tasks.each do |task|

  validates_associated :tasks

The code above is based on Ryan Bates' complex-form-examples application and from the Advanced Rails Recipes book.

After this patch

First you tell the Project model to accept nested attributes for its tasks:

class Project < ActiveRecord::Base
  has_many :tasks

  accept_nested_attributes_for :tasks, :allow_destroy => true

Then you could write the following template:

<% form_for @project do |project_form| %>
    <%= project_form.label :name, 'Project name:' %>
    <%= project_form.text_field :name %>

  <!-- Here we call fields_for on the project_form builder instance.
       The block is called for each member of the tasks collection. -->
  <% project_form.fields_for :tasks do |task_form| %>
          <%= task_form.label :name, 'Task:' %>
          <%= task_form.text_field :name %>

        <% unless task_form.object.new_record? %>
            <%= task_form.label :_delete, 'Remove:' %>
            <%= task_form.check_box :_delete %>
        <% end %>
    <% end %>
  <% end %>

  <%= project_form.submit %>
<% end %>

As you can see this is much more concise and easier to read.

Granted, the template for this example is only slightly shorter, but it's easy to imagine the difference with more nested models. Or if the Task model had nested models of its own.


Validations simply work as you'd expect; #valid? will also validate nested models, #save(false) will save without validations, etc.

The only thing to note is that all error messages from the nested models are copied to the parent errors object for error_messages_for. This will probably change in the future, as discussed on the ticket, but that's outside of the scope of this patch.

Let's look at an example where Task validates the presence of its :name attribute:

>> project = Project.first
=> #<Project id: 1, name: "Nested models patches", created_at: "2009-01-22 11:17:15", updated_at: "2009-01-22 11:17:15", author_id: 1>

>> project.tasks
=> [#<Task id: 1, project_id: 1, name: "Write 'em", due_at: nil, created_at: "2009-01-22 11:17:15", updated_at: "2009-01-22 11:17:15">,
#<Task id: 2, project_id: 1, name: "Test 'em", due_at: nil, created_at: "2009-01-22 11:17:15", updated_at: "2009-01-22 11:17:15">,
#<Task id: 3, project_id: 1, name: "Create demo app", due_at: nil, created_at: "2009-01-22 11:17:15", updated_at: "2009-01-22 11:17:15">,
#<Task id: 4, project_id: 1, name: "Scrutinize", due_at: nil, created_at: "2009-01-22 11:17:15", updated_at: "2009-01-22 11:17:15">]

>> = "" 
=> "" 

>> project.valid?
=> false

>> project.errors
=> #<ActiveRecord::Errors:0x23e4b10 @errors={"tasks_name"=>["can't be blank"]}, @base=#<Project id: 1, name: "Nested models patches", …, author_id: 1>>


By now you are probably wondering about the consistency of your data when validations passes but saving does not. Consider this Author model which I have rigged to raise an exception after save:

class Author < ActiveRecord::Base
  has_many :projects

  after_save :raise_exception

  def raise_exception
    raise 'Oh noes!'

Here's the Project data before an update:

>> project = Project.first
=> #<Project id: 1, name: "Nested models patches", created_at: "2009-01-22 11:17:15", updated_at: "2009-01-22 11:17:15", author_id: 1>

>> project.tasks
=> [#<Task id: 1, project_id: 1, name: "Write 'em", due_at: nil, created_at: "2009-01-22 11:17:15", updated_at: "2009-01-22 11:17:15">,
#<Task id: 2, project_id: 1, name: "Test 'em", due_at: nil, created_at: "2009-01-22 11:17:15", updated_at: "2009-01-22 11:17:15">,
#<Task id: 3, project_id: 1, name: "Create demo app", due_at: nil, created_at: "2009-01-22 11:17:15", updated_at: "2009-01-22 11:17:15">,
#<Task id: 4, project_id: 1, name: "Scrutinize", due_at: nil, created_at: "2009-01-22 11:17:15", updated_at: "2009-01-22 11:17:15">]

=> #<Author id: 1, name: "Eloy", created_at: "2009-01-22 11:17:15", updated_at: "2009-01-22 11:17:15">

Now let's delete the first Task and change the name of the second Task:

>> project.tasks_attributes = { "1" => { "_delete" => "1" }, "2" => { "name" => "Who needs tests anyway?!" } }
=> {"1"=>{}, "2"=>{"name"=>"Who needs tests anyway?!"}}

>> project.tasks.first.marked_for_destruction?
=> true

>> project.tasks.forty_two
=> nil # Oops, I meant #second of course… ;)

=> "Who needs tests anyway?!" 

Finally, let's try to save the Project instance:

RuntimeError: Oh noes!
  from /Users/eloy/code/complex-form-examples/app/models/author.rb:9:in `raise_exception_if_needed'

An exception was raised while saving one of the nested models. Now let's see what happened to the data:

SQL (0.1ms)   BEGIN
Task Destroy (0.3ms)   DELETE FROM `tasks` WHERE `id` = 1
Task Update (0.2ms)   UPDATE `tasks` SET `updated_at` = '2009-01-22 11:22:23', `name` = 'Who needs tests anyway?!' WHERE `id` = 2
SQL (17.0ms)   ROLLBACK

As you can see, all changes were rolled back. Both updates as well as the removal of records marked for destruction all happen inside the same transaction.

As with any transaction, the attributes of the instance that you were trying to save will not be reset. This means that after this failed transaction the first task is still marked for destruction and the second one still has the new name value.


This patch allows you to create forms for nested model as deep as you would want them to be. Creating, saving, and deleting should all work transparently and inside a single transaction.

Please test this patch on your application, or take a look at my fork of Ryan's complex-form-examples which uses this patch.

Your feedback is much appreciated. However, keep in mind that we can't possibly satisfy everyone's needs all at once. Please suggest additional features or major changes as a separate ticket for after the patch has been applied. The goal is to fix the bugs in this patch first so we all have a clean foundation to build on.

On a final note, I would like to thank David Dollar for the original :accessible implementation, Fingertips (where I work) for sponsoring the time that has gone into this patch, Manfred Stienstra for extensive help on the documentation, and in no particular order Lance Ivy, Michael Koziarski, Ryan Bates, Pratik Naik and Josh Susser for general discussion.

RailsConf 2009: Viva Las Vegas!

RailsConf 2009 is now open for registration. We’re going to Las Vegas this year. More precisely the Las Vegas Hilton from May 4th through 7th. It’s going to be a party for sure.

There has been such an incredible amount of activity since last year. We have the merging of Merb back into Rails, Rails 2.2 and 2.3, and probably a good showing of Rails 3.0. So we should be absolutely packed for great content this year.

It’s going to be hard to top 2008, though. I really thought that was a fantastic show. Great lineup of proposals, great speakers, and a great sense of community. Which is pretty hard to do when you have almost 2,000 people gathered. So we’ll try extra hard this year to outdo it.

So I hope to see many familiar and new faces this year. We have early registration open until March 16th, so you can save up to $200 by getting it done early.

Don’t forget to get your speaker proposal in either. You have until February 17th.

See you all in Vegas!