Rails 2.2: i18n, HTTP validators, thread safety, JRuby/1.9 compatibility, docs

Rails 2.2 is finally done after we cleared the last issues from the release candidate program. This release contains an long list of fixes, improvements, and additions that’ll make everything Rails smoother and better, but we also have a number of star player features to parade this time.

Internationalization by default
The most important is that Rails now includes a full-on internationalization framework and that it’s pre-wired from start. The work of the i18n group has been very impressive and it’s great to see that Rails finally ships with a solution in the box that’s both simple and extensible. Great job, guys!

Stronger etag and last-modified support
We’ve also added much better support for HTTP validators in the form of etag and last-modified. Making it so much easier to skip expensive procesesing if the client already has the latest stuff. This also makes it even easier to use Rails with gateway proxies.

Thread safety and a connection pool
Josh Peek has added thread safety to Rails and Nick Sieger from JRuby worked on getting Active Record a proper connection pool. So now all elements of Rails are thread safe, which is a big boon for the JRuby guys in particular. For C Ruby, we still need a bunch of dependent libraries to go non-blocking before it’ll make much of a difference, but work on that is forth coming.

Ruby 1.9 and JRuby compatibility
Jeremy Kemper has been rocking on both Ruby 1.9 and JRuby compatibility. Rails 2.2 is fully compatible with both, but again, there might be supporting libraries and gems that are not. Again, lots of work is going into making everything else fully compatible as well.

Better API docs, great guides
Finally, the last big push has been with the documentation of Rails. Pratik’s docrails project has made immense progress. Not only are the API docs much improved, but we also have a whole new guides section generated from documentation that now lives with the source. A true community project with lots of contributors. I’m sure both those new and old to Rails will greatly appreciate the strong focus on documentation.

To read about all these features and more in details, checkout the Rails 2.2 release notes — another one of those guides from the docrails project.

How to install
As always, you can install Rails 2.2 through RubyGems. We now require RubyGems 1.3.1, so be sure to update that first: gem update --system

Then you can install Rails: gem install rails

If you’re updating an existing application, you can run rake rails:update to get the latest JavaScript files and scripts.

From all of us to all of you, we hope you enjoy this release. It’s a true pleasure to see Rails make such big steps forward once again. Dig in, have fun, and we’ll be back with Rails 2.3 with even more before you know it.

This Week in Edge Rails

First up this week, a warning for those who don’t closely follow the state of the Rails repository – “edge” really means edge now. The bits for 2.2 are getting locked down for release, and the repository has been forked; for the moment, edge Rails is being identified as 2.3 , though that projected version number might change later. If you’re trying to install almost-released 2.2 bits on your machine, make sure you’re using the 2-2-stable branch, and not edge, which is currently seeing some major changes.

The 2-2-stable code is still seeing changes, but they’re either bug fixes or very small things. This week, that includes fixing a bug in assignment to has_one :through associations , some further tuning of CSRF protection , a fix to handling of checkboxes for Boolean attributes , updating the bundled copies of TZInfo, Prototype, and script.aculo.us, and some Ruby 1.9 compatibility work (though currently full Ruby 1.9 compatibility is targeted for Rails 2.3).

The biggest feature change in the 2.2 branch is the addition of explicit I18n support to newly-generated Rails projects, including a sample locale file, auto-loading all locales in config/locales, and sample settings in config/environment.rb. commit

Also worth noting in 2.2 is a chunk of code removal: a whole mess of special case tests for the SQL Server adapter have been chopped out of the Active Record test cases. That’s because Ken Collins has done tremendous work in making the SQL Server adapter work the way that Rails expects data adapters to work, giving us a big step in the area of backend portability. commit

On the actual edge code (the master branch in the repository), there’s a lot more action. With that branch just opened, some pent-up code has been checked in, and some big changes are being made. It’s an exciting time, and edge is definitely worth checking out. Here are some of the most notable changes in the past week.

One big set of changes has come from Jeremy Kemper, who has been overhauling the internal Rails testing to switch from Test::Unit::TestCase to ActiveSupport::TestCase. This work also includes requiring Mocha to test Rails (in the 2.2 code, some tests are skipped if you don’t have Mocha installed) and generally making the Rails testing strategy (both within core and for generated applications) more consistent moving forward.

If you’re one of the people who has always been bothered by the special-case naming of application.rb, rejoice! It’s been reworked to be application_controller.rb in the edge code. More info here and here . commit

Rails 2.3 will introduce the notion of default scopes : similar to named scopes, but applying to all named scopes or find methods within the class. For example, you can write default_scope :order => 'name ASC' and any time you retrieve records from that class they’ll come out sorted by name (unless you override the option, of course). commit

A lot of folks have adopted the notion of using try() to attempt operations on objects – Here’s Chris Wanstrath’s blog post introducing it. It’s especially helpful in views where you can avoid nil-checking by writing code like <%= @person.try(:name) %>. Well, now it’s baked right into Rails. commit

Also new on the syntactic sugar front is Enumerable#none? to check that none of the elements match the supplied block. commit

The render method has been getting smarter over the years, and it’s going to be even smarter in 2.3. If you have an object or a collection and the naming matches up, you can now just do <% render @article %> or <% render @articles %> and things will just work. Ryan Daigle has some more examples on this. commit

On a somewhat similar note, render_component goes from “deprecated” to “nonexistent” in 2.3. If you still need it, you can install the plugin . commit

The autolink helper has been refactored to make it a bit less messy and more intuitive. commit commit

There’s a fix to a memory leak connected to thread safety and asset tags, that could bite sites that were referencing a lot of external images. Aaron Batalion contributed the fix, as well as a blog post explaining the issue. commit and commit

Finally, it’s worth mentioning that some controversy has erupted over a change made to the 2.2 code five months ago – the addition of Array#second through Array#tenth as aliases for Array#[1] through Array#[9]. Without taking a stand on the controversy (I’ve done that elsewhere), I’ll just note that the most recent edge checkin as I write this trims this down to only support Array#second through Array#fifth – and uses the savings in overhead to implement Array#forty-two. commit

Potential Circumvention of CSRF Protection in Rails 2.1

There is a bug in all 2.1.x versions of Ruby on Rails which affects the effectiveness of the CSRF protection given by protect_from_forgery.

By design rails does not perform token verification on requests with certain content types not typically generated by browsers. Unfortunately this list also included ‘text/plain’ which can be generated by browsers.

Impact

Requests can be crafted which will circumvent the CSRF protection entirely. Rails does not parse the parameters provided with these requests, but that may not be enough to protect your application.

Affected Versions

  • All releases in the 2.1 series
  • All 2.2 Pre Releases

Fixes

The upcoming 2.1.3 and 2.2.2 releases will contain a fix for this issue.

Interim Workarounds

Users of 2.1.x releases are advised to insert the following code into a file in config/initializers/

> Mime::Type.unverifiable_types.delete(:text)

Users of Edge Rails after 2.2.1, should upgrade to the latest code in 2-2-stable.

The patch for the 2.1.x series is available on github. This will also apply cleanly to 2.2 pre-releases prior to this changeset released on Thursday November 13th at 11:19:53 2008 CET. Users with edge-rails checkouts after that date, are advised to upgrade to the latest code in 2-2-stable.

Thanks to Steve from Coderrr for reporting this issue.

New Rails 2.2 i18n defaults

I just reduced the housework needed to setup a new Rails application with i18n. All new applications will ship with a config/locales directory that’s automatically wired up in the load path for i18n. So you can just drop .yml or .rb locale files in there and they’ll be instantly available for translation.

There’s also a sample config/locales/en.yml file in there to give you a starting point. In addition, the initializer is now wired up through the Rails config. The new default environment.rb provides these pointers:

# The internationalization framework can be changed 
# to have another default locale (standard is :en) or more load paths.
# All files from config/locales/*.rb,yml are added automatically.
# config.i18n.load_path << Dir[File.join(RAILS_ROOT, 'my', 'locales', '*.{rb,yml}')]
# config.i18n.default_locale = :de

So on a fresh Rails 2.2 application, you’ll be able to do see it all wired up out of the box (the :hello key is from the config/locales/en.yml demo file):

$ ./script/console
>> I18n.t :hello
=> "Hello world"

Rails 2.2 final is just around the corner. We’ve been ironing out the last bugs and added the last amount of polish to make this a kick ass release. Also, work on 2.3 / 3.0 has already begun in master as well since we’ve branched for 2.2 a while back.

Rails 2.2 RC2: Last stop before final

Rails 2.2 has been baking for long enough now. This is the last taste before the goodies are served. So please install and check it out. See if you can find any regressions or bugs in any of the new stuff, so we can have it all delicious by the time we ring the dinner bell (ok, ok, I’ll put down the food metaphor now).

This release also conciedes with the fact that we’ve branches 2-2-stable, which means that master is now actually targeting Rails 2.3/3.0. There’s also a tag available for this RC as v2.2.1.

If you missed RC1, have a look at the Rails 2.2 release notes to see the major additions. You can see what’s new since RC1 in these two This Week in Edge Rails.

To install, you must first have RubyGems 1.3.1:
gem update --system.

Then you can:
gem install rails -s http://gems.rubyonrails.org

Enjoy!

This Week in Edge Rails

The important news in edge Rails this week is the imminent release of Rails 2.2.1 – otherwise known as Rails 2.2 RC2. Getting ready for this release did lead to some significant changes in the Rails codebase.

First, it’s very likely that you’ll need to upgrade rubygems to run RC2: the required version of rubygems is now 1.3.1, which was just released yesterday. This dependency is part of the continued work to make vendored gems useful and stable. You may find that updating rubygems is less than smooth, depending on your current version; check out this article if you have any trouble. commit

The Rails routing engine has seen some serious work over the past week as well. For starters, Jeremy Kemper committed several fixes to the core routing engine that cut down on object creation and RegExp creation, trimming memory use. commit commit There are also new :only and :except options for map.resources, which can help cut down memory use if you have a lot of resource routes – see these articles for details (though there have been some tweaks in the way nested limited routes work after those were written). commit commit commit

The new ActiveRecord connection pooling code has seen some tuning as well, making it more efficient in development model and avoiding some issues with the Oracle adapter. commit

Polymorphic URLs now behave more intuitively if one of their parameters is nil. For example, a call to polymorphic_path([project, filter, @issue]) with a nil filter now returns project_issue_url instead of a NoMethodError. commit

The request forgery protection feature in Rails has been tightened up so that it only applies to HTML-formatted content requests. There is substantial discussion on the Lighthouse ticket that led to this change, but the bottom line is that the old implementation had some bugs, notably making destroy actions inaccessible via XML. Other types of requests are protected by other means – for instance, the same origin policy on AJAX requests substitutes for request forgery protection there. commit

This Week in Edge Rails

Rails, as you probably know, is under active development. So, for those of you who don’t have time to read every commit to the source, we’ve decided to revive this section of the weblog. This time around, I’m covering 3 weeks of commits: the time since Rails 2.2 RC1 (otherwise known as Rails 2.2.0) was released. Though there aren’t any major new features being added as Rails drives towards the 2.2 release, that doesn’t mean the source has been completely quiet: there have been about 75 commits in that three-week period. Here’s a look at some of those changes.

In the run-up to 2.2, we’re seeing a batch of little bug fixes, as people try to ensure quality in the release. These include:

  • Squashing a binary data corruption bug that surfaced in the PostgreSQL adapter. commit
  • The regex behind redirect_to can now accept a wider variety of URL schemes, making it possible to redirect to some destinations that were previously inaccessible. commit
  • A regression in date_select and datetime_select that could raise a Null Pointer Exception under some circumstances has been fixed. commit
  • The sanitize helper has been fixed to avoid double escaping already properly escaped entities. commit
  • FormTagHelper has been stopped from generating illegal HTML if the name contains square brackets. commit
  • A memory leak was squashed in Active Record scoped methods. commit

Some of the major features for 2.2 have been getting fine-tuned as well. There’s been work to clean up some loose ends in the thread safety department, and changes to make the I18n backend reload its translations in development mode. The included Prototype bits were bumped to the latest 1.6.0.3 release. The code for configuring, loading, and vendoring gems has had some attention, and the code for maintaining database connection pools has come in for some fine-tuning as well.

Just because we’re in feature freeze doesn’t mean that a few new features can’t sneak in:

  • The current_page method is a bit more reliable now in that it ignores options you don’t explicitly supply (making it more friendly to URLs that use the query string for pagination and the like). commit
  • The default logging has been cleaned up to be less chatty: you’ll see fewer duplicate log messages as Rails goes about its business. commit
  • The render method now takes a :js option to allow you to directly render inline JavaScript without using RJS. commit
  • If you’ve got a current (Ruby 1.8.7 or greater) version of Ruby, Action Mailer turns on STARTTLS if the server supports it; this makes Action Mailer compatible with GMail without the need for plugins. commit

One final note: I’m deliberately not trying to cover every single commit here; just those ones that struck me as most interesting. But if I left out something that you think is highly significant, feel free to add a pointer in the comments!

Rails Guides Wants You

If you haven’t looked at the state of Rails documentation lately, it’s time to look again. The new Ruby on Rails Guides page includes 14 separate guides for Rails developers, with topics ranging from “Getting Started” to routing, security, testing, and debugging. That’s over 70,000 words of help content for Rails users that didn’t exist two months ago when we launched the Rails Guides project.

But we’re not done yet! We’re starting phase 2 of the Guides project, and planning a fresh batch of content to add to what’s already there. Our goal is to have a single page where you can find all of the information you need to be an effective Rails developer. Remember, though: this is open source. That means we want your help too!

Here’s what you can do to get involved:

  • Read about the process of and rewards for contributing on the Hackfest page.
  • Check the list of available tickets in our Lighthouse project, and sign up to write a guide.
  • Submit corrections, suggestion, bugs, or patches for the existing guides. You’ll find a link to the relevant Lighthouse ticket at the bottom of each guide.
  • Let us know what other guides you think should be added – whether you want to write them, or just hope that someone else will. Just leave a note in the comments here and we’ll get your idea into the process.

You’ll usually find some of the documentation team hanging around in #docrails on IRC. Come join us and help the community!

3 Weeks in Rails (October 29, 2008)

It’s been 3 weeks (I know I’ve been slacking). However, it’s time to write out another summary of information that any Rails developer might want to know about. Detailed audio versions of these notes can be found on the Rails Envy Podcast #51, #52, and #53.

You may already be aware that Rails 2.2 RC1 was released last Friday. For a glimpse at the new features you can read through the Release Notes. However, if you’re looking for something more comprehensive check out the Envycast on Ruby on Rails 2.2^ or the What’s New PDF by Carlos Brando.

Rails 2.0.5 and Rails 2.1.2 were also pushed in the last few weeks, mostly just plugging up a few small security concerns. If you’re on 2.x, you should probably take the time to upgrade.

If you’re taking advantage of the localization features of Rails 2.2, there are two libraries you should probably be aware of. First, Diego Carrion recently created a fork of restful_authentication where he added full support for i18n. Secondly, Karel Minarik recently released a plugin for doing localized_country_select so you can display countries the appropriate language.

If you need your Rails application to receive emails, one way to do it is to use gmail IMAP. John Nunemaker wrote up a nice walkthrough showing all the scripts need to parse email out of gmail.

Hosting, Performance, and Tuning

With Rails 2.2 thread safety, you might assume that brings a performance boost for everyone. However, this is not always the case and Pratik Naik explains why.

Ilya Grigorik wrote a blog post about Scaling Rails with MYSQL Plus where he uses the Non-Blocking MySQL driver from Neverblock to get some increased performance out of ActiveRecord which is quite impressive.

If you need to implement full text search in your Rails application, and you are already thinking Sphinx, you may want to check out the Thinking Sphinx PDF by Pat Allan over on Peepcode.

Library News

If you’re a fan of resource_controller (skinny REST controllers) and Shoulda you shoulda definitely check out the starter app by James Golick called Blank.

The next time you need to build a “Software As A Service” website (like basecamp), check out Service Merchant. This gem sits on top of Active Merchant and gives you everything you need to do Subscription Billing.

Do you ever forget your Rails routes? There’s always the “rake routes” command, but that’s not very user friendly. You might want to check out Vasco. Vasco is a Route explorer for Rails which provides a nice web interface to browse through and test all your Rails routes.

If you ever need to build a Rails application which is accessible on multiple domains or multiple paths (like foo.com or bar.com or a.com/foo) then take a look at the Rails Proxy Plugin by Sean Huber. This plugin allows you to dynamically respond to proxied requests by detecting the incoming path and properly setting the session domain, default host, and relative url root.

If you need an easy way to test your plugin which extends ActiveRecord, check out acts_as_fu, which aside from it’s unfortunate name, is pretty slick.

If you came over from PHP, you’re probably familiar with phpMyAdmin. One of the Rails Rumble teams made a Ruby version of phpMyAdmin that’s definitely worth checking out if you’re missing a quick web interface to your db.

Event News

The Rails Rumble is over and you only have 3 more days to vote (voting closes on Midnight November 1st). Cast your vote! It’s good practice for next Tuesday (least in the US).

If you’re over in London, Ruby Manor is taking place November 22nd. Looks like it’s going to be a fun unconference type of event.

Lastly, Rubyconf is next week here in Orlando, Florida where it’s been kinda chilly lately. Definitely pack something warm just in case, and see you next week!

Image Credit: Blue Sky on Rails by ecstaticist, Analog Solutions 606 Mod by Formication, RailsConf Europe 2006 by Paul Watson, Rainbow by One Good Bumblebee
^ In the interest of full disclosure, I do produce Envycasts, and profit from the sale of the screencasts.