Timing Weakness in Ruby on Rails

There is a weakness in the code Ruby on Rails uses to verify message
digests in the cookie store. Because it uses a non-constant time algorithm to
verify the signatures an attacker may be able to determine when a forged
signature is partially correct. By repeating this process they may be able to successfully forge a digest.

Versions Affected:  2.1.0 and *all* subsequent versions.
Fixed Versions:     2.3.4, 2.2.3

Impact

Due to issues like network latency, non-deterministic GC runs and other
issues it is unlikely that this attack could be exploited in the wild
within a reasonable timeframe. However users should still upgrade as
soon as possible to remove the weakness.

Releases

The 2.3.4 and 2.2.3 releases will be made available shortly and will contain fixes for this issue amongst others.

Patches

In order to provide the fixes for users who are running unsupported
releases, or are unable to upgrade at present we have provided patches
against all affected stable release branches.

The patches are in a format suitable for git-am and consist a single
changeset which implements

Credits

Thanks to Coda Hale for reporting the bug to us, and helping us with the fixes.

XSS Vulnerability in Ruby on Rails

There is a vulnerability in the escaping code for the form helpers in
Ruby on Rails. Attackers who can inject deliberately malformed unicode
strings into the form helpers can defeat the escaping checks and inject
arbitrary HTML.

Versions Affected:  2.0.0 and *all* subsequent versions.
Not affected:       Applications running on ruby 1.9
Fixed Versions:     2.3.4, 2.2.3
Candidate CVE:      CVE-2009-3009

Impact

Due to the way that most databases either don’t accept or actively
cleanse malformed unicode strings this vulnerability is most likely to
be exploited by non-persistent attacks however persistent attacks may
still be possible in some configurations.

All users of affected versions are advised to upgrade to a fixed versions.

Releases

The 2.3.4 and 2.2.3 releases will be made available shortly and contain fixes for this issue.

Patches

In order to provide the fixes for users who are running unsupported
releases, or are unable to upgrade at present we have provided patches
against all affected stable release branches.

The patches are in a format suitable for git-am and consist of two
changesets. The code for cleansing multi-byte strings, and the
introduction of that code to the relevant helpers.

Please note that only the 2.2.x and 2.3.x series are supported at
present. Users of earlier unsupported releases are advised to upgrade
sooner rather than later as we cannot guarantee that future issues will
be backported in this manner.

Credits

Thanks to Brian Mastenbrook for reporting the vulnerability to us, and Manfred Stienstra from Fingertips for his work with us on the fix.

A Month in Rails

Lots of great content coming out of the community in the past month. Below you’ll find some of the most useful tutorials and libraries I’ve found over the past few weeks. These stories came directly from the Ruby5 podcast, which covers news from the Ruby and Rails community twice weekly.

Improving your Rails code

James Golick released a gem called Observational recently which provides you with a better way of using observers in Rails. Instead of creating one file per observer, this gem allows you to define multiple observed objects and specific methods to call for each object’s events.

If you want to develop a Rails app that takes advantage of Subdomains Taylor Luk has the recipe. He recommends using subdomain-fu, shows how to use a Proxy PAC file in development, and introduces a piece of Rack middleware he wrote which allows you to use full custom domains in your application.

If you like to TATFT like the rest of us, I have two libraries to tell you about. The first is a gem by the guys over at Devver called Construct which makes it easy to test code which interacts with your filesystem. The second is Blue Ridge by Larry Karnowski and Chris Redinger which makes it easy to write tests for your javascript. Blue Ridge has been out for a while, but this week Noel Rappin wrote a great introductory article to get you started.

Just yesterday Fabio Akita put together a screencast showing how the “Weblog in 15 minutes” code could be simplified using Inherited Resources, a gem by José Valim which helps reduce controller code duplication. The gem uses the same sort of technique you may have seen before with make_resourceful or resource_controller, but has improved syntactic sugar.

Libraries you should know about

Patrick McKenzie released A/Bingo, a gem/plugin for your Rails application that makes A/B Testing easy. It uses a fairly intuitive and simple interface for defining your tests and provides information on which sample performed best and by what margins.

Steve Richert released a gem called vestal_versions which allows you to keep a history of all of your ActiveRecord model changes in your database. It takes advantage of several newer features in Rails 2.2+ including recognizing dirty objects.

Railscast #176 by Ryan Bates covered Searchlogic by Ben Johnson, which makes it really easy to create advanced search forms in Rails.

David Bock released new gem called Crondonkulous which allows you to write crontab recipes in Ruby from within your Rails application. These recipes get automatically published to your server’s crontab when you deploy.

Security

James Harton released Lockbox and acts_as_lockbox, which provide a simple interface for securing sensitive data by managing RSA public key cryptography for your application. This allows you to define which attributes are sensitive and provides an application-wide locking and unlocking ability.

Hongli Lai wrote up a great article on keeping your user’s passwords secure. He writes about how to store passwords, hashing algorithms, salting, and more. Specifically, he recommends using Blowfish File Encryption, or “bcrypt,” because it’s a slower-running algorithm which will make it more difficult to crack.

In your Database

Mauricio Linhares released a plugin for Rails which allows you to do master / slave replication. Unlike masochism, master_slave_adapter works in conjunction with the Rails database connection pool and is implemented as a new database adapter. So, no monkey patching necessary.

Matt Jankowski provided a great article on properly indexing your database for your Rails application. He covers indexing validation and STI columns, state columns for state machines, association columns, and more.

The developers of xing created a plugin called FlagShihTzu. It’s not a dog.. or even a multiplayer game for your Tamagotchi. FlagShihTzu stores any number of ActiveRecord boolean model attributes as a single database field, using each bit as unique keys. But, the interesting part is that the interface remains exactly the same to the rest of your application.


Thanks for reading and if you have any news or libraries you’d like to get the word out about, feel free to drop me a line by submitting news over at Ruby5.

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. Orange County Security by henning

Gem Packaging: Best Practices

Understand Ruby’s Load Path

When you call load or require a new file, Ruby searches through the files in its load path. This allows you to require files relative to the load path without specifying the files full system path.

The initial load path contains paths for Ruby’s standard library. There are three aliases that point to Rubys global load path array: $:, $-I, $LOAD_PATH. You can append or prepend you own libraries to this list. The load path can also be modified from the command line with the -I flag.

Here is the initial load path on my Mac.

  >> $LOAD_PATH
  => ["/Users/josh/.rip/active/lib",
      "/Library/Ruby/Site/1.8",
      "/Library/Ruby/Site/1.8/powerpc-darwin9.0",
      "/Library/Ruby/Site/1.8/universal-darwin9.0",
      "/Library/Ruby/Site",
      "/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8",
      "/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/powerpc-darwin9.0",
      "/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/universal-darwin9.0",
      "."]

There are a few far-too-common mistakes people make with load paths.

Respect the global load path

When you package up your new rubygem to share with the world, you need to be careful with the files you place directly in lib/. Rubygems (and almost all other ruby package mangers) will add your gem’s lib/ to the load path. This means any file placed in the top level of lib/ will be directly requirable by anyone using the gem.

Bad gem example:
  `-- lib
      |-- foo
      |   `-- cgi.rb
      |-- foo.rb
      |-- erb.rb
      `-- set.rb

It may seem harmless to call files whatever you’d like in your package because you are “namespaced” in your own package. But if lib/ is prepended to $LOAD_PATH it will clobber Ruby’s built in erb and set libs. require 'erb' would no longer require Ruby’s builtin erb library, but this package’s version of it.

The safe (and correct) way would be to namespace your files under another directory. Its conventional to create a folder within lib with the same name as your gem. Then we would put all our dependency files under lib/foo/ instead of at lib/ root.

This is sort of a gray area. There is no strict rule that you must put all your files under a folder with your package name. It is okay to have multiple files at your root lib directory as long as you intend for people to require them separately. Namespace internal dependency files that you don’t expect for people to require directly.

Requiring other files relative to each other
  require File.join(File.dirname(__FILE__), "foo", "bar")
  # or
  require File.expand_path(File.join(File.dirname(__FILE__), "foo", "bar"))

If you’re using File.dirname(__FILE__) with require, you’re doing something wrong.

The fix is simple, require files relative to the load path.

  require "foo/bar" 

Its interesting that the 3 previous require examples are totally different. Ruby is only able to track which files it has required by the exact path you gave it. The first is relative your current directory (”./lib/foo/bar”), the second is the full expanded system path (”/usr/local/lib/ruby/gems/foo/lib/foo/bar”), and the third is relative to the load path (”foo/bar”). require treats each as a different file, so it may end up loading the file multiple times.

Depending on files outside the load path

This is a more severe case of the previous example.

  module Rack
    module Test
      VERSION = ::File.read(::File.join(::File.dirname(__FILE__), "..", "..", "VERSION")).strip
      # ...
    end
  end

Your gem’s folders may be separated and reorganized on install. If someone wants to “vendor” your library, they should only have to copy everything under lib/. Everything outside lib/ is not important for running the code. Never expect your lib or test folders to be one level up. A minimalist installer, such as rip, will only install your bin and lib directories. Any file your package needs to access should be under lib and properly namespaced in a folder to avoid collisions. If you try install this version of rack-test with rip, require 'rack/test' will fail because ../VERSION doesn’t exist.

Libs don’t need to mange $LOAD_PATH

Its not the package’s responsibility to setup and manage the load path. Instead rely on the package manger to set it up for. When rubygems activates a gem, it adds your package’s lib folder to the $LOAD_PATH ready to be required normally by another lib or application. Its safe to assume you can relative require any file in your lib folder.

  unless $LOAD_PATH.include?(File.expand_path(File.dirname(__FILE__)))
    $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__)))
  end

It should be safe to remove code like that.

TIP: Setup your test runner to configure your paths for local development

If your trying to develop your lib locally, dealing with all this load path stuff seems like a pain in the ass. This is where rake tests come in handy.

Rake’s test task will automatically push lib into your path when your test unit tests. So you don’t need File.join(File.dirname(FILE), ”..”, “lib”, “foo”) anywhere in your tests. You may want to consider adding the test directory to your path if you have “test_helper” that you need to require.

  Rake::TestTask.new do |t|
    t.libs << 'test'
  end

Unfortunately Rspec doesn’t even add lib to your path for you. You can fix this with:

  Spec::Rake::SpecTask.new do |t|
    t.libs << 'lib'
  end

If you want to run a single test, you can add lib to the $LOAD_PATH with a command line flag. (This started a long debate when the change was made to Rails)

  ruby -Ilib test/test_foo.rb
Provide a VERSION constant

If you release the Awesome gem, provide Awesome::VERSION. When using Rubygems, it’s possible to ask Rubygems for the version of the gem you’re using, but when using an alternate package manager, the only way to find out what version is loaded is by introspection into the Ruby code itself.

Don’t depend on rubygems

When I use your library, deploy your app, or run your tests I may not want to use rubygems. When you “require ‘rubygems’” in your code, you remove my ability to make that decision. I cannot unrequire rubygems, but you can not require it in the first place. – Ryan Tomayko

Its safe to remove require "rubygems" from your lib since code loading it probably did this already. It makes it harder (but not impossible) for people to use alternative ways of setting up the load path because there is no way to “unrequire” rubygems. There are many other package management solutions out there, like rip, bundler, or managing $LOAD_PATH by hand.

Avoid declaring rubygem dependencies in lib/. This means removing gem "foo". This creates a hard dependency on Rubygems when you should be specifying you gem dependencies in your gemspec. Rubygems already hooks into require and will automatically resolve these dependencies at runtime. A simple require will trigger the lookup via rubygems, or will just require it if it’s been added to the load path by another system. Moving dependency specification outside the lib is more flexible for other package managers can do so at install time.

In addition to removing gem, do not wrap your load checks with rescue Gem::LoadError or rescue Gem::Exception. If you need to gracefully skip over load errors, Gem::LoadError inherits from LoadError so replacing it with rescue LoadError will work.

  # Bad
  begin
    gem "rack" 
    require "rack" 
  rescue Gem::LoadError
    puts "Could not load 'rack'" 
    exit
  end

  # Good
  begin
    require "rack" 
  rescue LoadError
    puts "Could not load 'rack'" 
    exit
  end

Why should I care?

I wasn’t aware of any of these issues until Ryan wrote up his post on why requiring rubygems is wrong at the beginning of 2009. And I feel many other rubyists have just overlooked these issues since rubygems has been our only solution. The foundation of Ruby library management is built on the load path system and its important for every ruby gem author to understand how it works.

We’re working on it

Fixing every ruby library is easier said than done (There are 12,000+ hosted on RubyForge at the time of posting). Rails is currently in violation of a few of these rules. But we’re working hard to fix them. We also need to fix all the gems that we depend on. Ideally, we’d like Rails 3 to boot w/o rubygems and allow you use to whatever package management strategy you’d like.

Further reading

Rubygems Good Practice « Katz Got Your Tongue?
Why require ‘rubygems’ In Your Library/App/Tests Is Wrong

Three reasons to love ActionController::Responder

A couple weeks ago, I wrote about the newly added ActionController::Responder which summarizes your application behavior for a specified format in just one place. For example, the default html behavior is written as:


class ActionController::Responder
  def to_html
    if get?
      render
    elsif has_errors?
      render :action => (post? ? :new : :edit)
    else
      redirect_to resource
    end
  end
end

Here are three examples of the flexibility this new layer can provide.

1) HTTP Cache

A simple, but quite powerful use for responder is apply HTTP cache to all your resources easily. For simplicity, let’s cache just get requests that are not handling a collection:


module CachedResponder
  def to_html
    if get? && resource.respond_to?(:updated_at)
      return if controller.fresh_when(:last_modified => resource.updated_at.utc)
    end
    super
  end
end

2) I18n flash messages

Is a common practice that all controllers, when the create, update and destroy actions are handled with success, a flash message is shown to the user. We could easily remove the flash messages from our controllers and let them be handled by the responder with the help of the I18n framework. And it’s quite straightforward to accomplish:


module FlashResponder
  # If it's not a get request and the object has no errors, set the flash message
  # according to the current action. If the controller is users/pictures, the
  # flash message lookup for create is:
  #
  #   flash.users.pictures.create
  #   flash.actions.create
  #
  def to_html
    unless get? || has_errors?
      namespace = controller.controller_path.split('/')
      namespace << controller.action_name
      flash[:success] = I18n.t(namespace.join("."), :scope => :flash,
       :default => "actions.#{controller.action_name}", :resource => resource.class.human_name)
    end
    super
  end
end

The first question then arises: what if I don’t want to add a flash message in an specific situation? This can be solved using options, since all options sent to respond_with are sent to the responder, we could use it in our favor as well:


class MyResponder < ActionController::Responder
  def to_html
    unless get? || has_errors? || options.delete(:flash) == false
      namespace = controller.controller_path.split('/')
      namespace << controller.action_name
      flash[:success] = I18n.t(namespace.join("."), :scope => :flash,
       :default => "actions.#{controller.action_name}", :resource => resource.class.human_name)
    end
    super
  end
end

And we can invoke it as:


class PostsController < ApplicationController
  def create
    @post = Post.create(params[:post])
    respond_with(@post, :flash => false)
  end
end

3) Instant pagination

Some people already start a project with pagination from scratch, others add at some point. Nonetheless, pagination is more like a rule than a exception. Can that be handled by Rails 3? First, let’s check an index action with respond_with:


class PostsController < ApplicationController
  def index
    @posts = Post.all
    respond_with(@posts)
  end
end

Right now, when we call Post.all, it returns a collection of posts in an array, so the pagination should be done before the collection is retrieved. Thanks to Emilio and his work integrating ActiveRelation with ActiveRecord, Post.all will return an ActiveRecord::Relation that will be sent to the responder:


module PaginatedResponder
  # Receives a relation and sets the pagination scope in the collection
  # instance variable. For example, in PostsController it would
  # set the @posts variable with Post.all.paginate(params[:page]).
  def to_html
    if get? && resource.is_a?(ActiveRecord::Relation)
      paginated = resource.paginate(controller.params[:page])
      controller.instance_variable_set("@#{controller.controller_name}", paginated)
    end
    super
  end
end

However, the code above is definitely smelling. Set the paginated scope seems more to be a controller responsability. So we can rewrite as:


module PaginatedResponder
  def to_html
    if get? && resource.is_a?(ActiveRecord::Relation)
      controller.paginated_scope(resource)
    end
    super
  end
end

class ApplicationController < ActionController::Base
  def paginated_scope(relation)
    instance_variable_set "@#{controller_name}", relation.paginate(params[:page])
  end
  hide_action :paginated_scope
end

As previously, you could make use of some options to customize the default pagination behavior.

Wrapping up

All the examples above were contained in modules, that means that our actual responder has yet to be created:


class MyResponder < ActionController::Responder
  include CachedResponder
  include FlashResponder
  include PaginatedResponder
end

To activate it, we just need to overwrite the responder method in our application controller:


class ApplicationController < ActionController::Base
  def paginated_scope(relation)
    instance_variable_set "@#{controller_name}", relation.paginate(params[:page])
  end
  hide_action :paginated_scope

  protected
  def responder
    MyResponder
  end
end

While those examples are simple, they show how you can dry up your code easily using Responder. And you? Already thought in an interesting use case for it?

Upgrading to Snow Leopard

Last Friday, Apple released their new OS version: Snow Leopard. Upgrading to SL is very easy and even gives you back quite a lot of HD space. However a few things have changed in the OS and you need to understand what is going on so you won’t get frustrated with the updating process and won’t be wasting time fighting with the system.

Snow Leopard

The key change for us Ruby developers, is the fact that, in Snow Leopard, all the interpreted languages (including Ruby) are now running in 64-bit by default (obviously, only if you have a 64-bit machine). For pure Ruby applications and libraries this shouldn’t pose any problems. But if you are migrating from a Leopard environment where you compiled C extensions for 32-bit only, these gems won’t properly load in Snow Leopard. Same thing goes for libraries you might have compiled in 32-bit mode and that you might want to use on your migrated system.

Something else you need to know: Snow Leopard now comes bundled with Ruby 1.8.7 instead of 1.8.6. This should not be a problem since Rails has been running on Ruby 1.8.7 for a long time and Rails 3 will require Ruby 1.8.7 and prefer Ruby 1.9.2.

Here is a quick rundown of common tasks you might have to do to migrate properly.

Install Snow Leopard developer tools

On the Snow Leopard DVD, under “Optional Installs”, install “Xcode.mpkg”. Use all default options.

Passenger

$ sudo gem install -r passenger
$ sudo passenger-install-apache2-module Press Enter when prompted. Passenger will compile and install its Apache module. Press Enter when prompted the second time too.

$ cd /etc/apache2

Open httpd.conf in your text editor (if you use TextMate, try running mate httpd.conf from the command line) and look for a line like “LoadModule passenger_module” and some lines following that have “passenger” in them too. Delete them. If you don’t see them them, move your cursor to the end of the file.

Then insert these lines:

LoadModule passenger_module /Library/Ruby/Gems/1.8/gems/passenger-2.2.4/ext/apache2/mod_passenger.so
PassengerRoot /Library/Ruby/Gems/1.8/gems/passenger-2.2.4
PassengerRuby /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby

MySQL

To avoid weird issues with MySQL, it’s strongly recommended to upgrade to the 64-bit version. Start by shutting down mysqld if it’s running. (Depending on how you installed MySQL, you might be able to use the preference panel, or use sudo /opt/local/share/mysql5/mysql/mysql.server stop if you installed it using MacPorts)

Now install the Mac OS X 10.5 (x86_64) version of mysql from here

When the disk image opens, first install “mysql-5.1.37-osx10.5-x86_64.pkg”. Use all default options.

Next install “MySQLStartupItem.pkg”. Use all default options.

Next install “MySQL.prefPane”. Double-click to install it. Choose to replace the existing preference pane when prompted. (Apparently the preference pane is still 32-bit.) At this point you can click “Start MySQL Server” to start the server and verify it works.

Unmount the MySQL disk image.

Since you are upgrading from Leopard, your mysql gem is compiled for 32-bit only and therefore needs to be recompiled. However, it’s not that simple, the mysql gem is a bit of an exception. Under Snow Leopard when you do a gem install for a C extension it tries to build the extension for two architectures: i386 (32-bit) as well as x86_64 (64-bit). The problem is that the binary from mysql.com is not universal and therefore we need to force the C extension to be only compiled in 64-bit.

$ sudo env ARCHFLAGS="-arch x86_64" gem install mysql -- --with-mysql-config=/usr/local/mysql/bin/mysql_config

note: You shouldn’t have to set the ARCHFLAGS to compile any other gems.

MacPorts

You should be all set. However, if you are relying on any libraries you compiled on Leopard, you probably will have to recompile them. MacPorts users shouldn’t think that it will be automatically done for them.

You have different options to upgrade your ports.

The easiest way is to upgrade MacPorts:

$ sudo port selfupdate
$ sudo port sync
$ sudo port upgrade --force installed

Other native gems

Check this script to get a precise list of gems requiring to be reinstalled and some help with the upgrade process. Basically, you just need to reinstall the few gems using C extensions.

What's New in Edge Rails: No REST for the weary

This week’s post will be rather short and sweet. The notable commits of the week seemed to revolve mainly around refactoring and even slightly altering the way some of the bits work. Lets get into it:

I’m Partially impressed

Yehuda Katz was able to simplify some of the partial rendering logic this week, although in doing so seems to very slightly alter the call methodology. So now, when calling the local object from within a partial, you will have the choice of using either the partial name (i.e. “_post.html.erb” would be “post”) as the reference for the local object, or you may make it unique by passing in the :as option (i.e. render :partial => "post", :as => "poster_boy" would be “poster_boy”). You no longer have the option of using both interchangeably from within your partial. Also, the :object option for render :partial has been removed, in favor of the methods previously mentioned.

We won’t Accept it

The way in which Rails handles incoming Accept headers has been updated. This was primarily due to the fact that web browsers do not always seem to know what they want … let alone are able to consistently articulate it. So, Accept headers are now only used for XHR requests or single item headers - meaning they’re not requesting everything. If that fails, we fall back to using the params[:format].

It’s also worth noting that requests to an action in which you’ve only declared an XML template will no longer be automatically rendered for an HTML request (browser request). This had previously worked, not necessarily by design, but because most browsers send a catch-all Accept header (“*/*”). So, if you want to serve XML directly to a browser, be sure to provide the :xml format or explicitly specify the XML template (render “template.xml”).

I’ll tell you where you can go…

Josh Peek finally removed the deprecated “best fit” route generation support. Mostly for the sake of speed and maintainability, the new router will simply use the first matching route in your routes.rb file, rather than the “best” match. If you’ve been working at all on the Edge and haven’t noticed the deprecation warnings, then this probably won’t affect you.

Oh, so that’s why!

Jay Pignata provided a patch this week to help out all of you RESTful API developers. Previously, when a client sent invalid XML or JSON to your server, Rails would 500 with an oh-so-descriptive /!\ FAILSAFE /!\ error in your logs. This wasn’t much help if you were trying to debug it. So, with this patch, you’ll now get to look at the raw data that was posted to your server in your logs.

Speaking of Resources

Finally, a few updates went into ActiveResource this week which will make it a lot more familiar to those of us who are more comfortable with ActiveRecord. Validation support has been added, which will allow you to both validate your resources locally - before transmission - and remotely. ActiveResource no longer throws a ResourceNotFound error when you attempt to find a set of undefined resources [Resource.find(:all)]. Instead, ActiveResource is reverting to the more ActiveRecord-like empty set/nil response. And last, but not least, resource.save! will now raise a ResourceInvalid unless the resource is, actually .. well .. valid?

That’s it for this week’s update on Edge Rails. I hope that you’ve enjoyed it.

Photo: Hood River Sunset by Bernt Rostad

What's New in Edge Rails: The BugMash Edition

Another week, another update on Edge Rails. And man, you aren’t making this easy on me, are ya? This weekend, in case you hadn’t already heard, was the first Rails and RailsBridge BugMash. If my count is correct, there were roughly 300 commits to the Rails master over the past six days, with most of them pushing in over the weekend. Talk about a trial by fire! There’s a lot of really good stuff in here, so let’s get started:

All I ever wanted was a little Validation

ActiveRecord (or probably more accurately, ActiveModel) received a lot of validation love this weekend.

  • Thanks to James Hill you can now have your validations read from a custom method. This will allow you to more easily validate non-column - instance variable - data, for example.
  • Adam Keys added support for exclusive ranges in validates_length_of. So, validates_length_of :name, :within => (5...10) will actually restrict the valid length to between 5 and 9.
  • Thanks to Zac Williams, validates_length_of :name, :maximum => 10 will now allow nil values to validate, by default.
  • What good is validates_format_of if you can’t validates_format_of :without => /.../? Well, not much, let me tell you… Elliot Winkler provided a patch do to just that.
  • And last, but certainly not least Jeff Dean committed a great patch, which now brings to us: validates_with. This little beauty now allows you place validation code into an external class. And that, my friends, means better encapsulation of responsibility, I’ll bet on better readability, and even shared validation logic across your application or possibly even gems. Nice job, Jeff.

We’re so much more Resourceful

There were quite a number of updates to ActiveResource over the weekend. And, I’m sure many of you are going to be quite thankful for some of these:

  • ActiveResource now supports HTTP proxies thanks to Marshall Huss. This should be highly useful in large corporate and other firewalled or isolated environments.
  • ActiveResource gets SSL options from Roy Nicholson. This allows you to use X509 certificates, SSL timeouts, peer verification, and more.
  • ActiveResource.exists? got some polish from Jatinder Singh. And, by polish, I really mean that now it works. Instead of raising Net::HTTP errors.
  • Fabien Jakimowicz added JSON error reporting support. So, now regardless of whether you’re using either XML or JSON, errors will be correctly reported back to you.

There’s strength in numbers

Thanks to Dan Cheail, we finally get a grouped_collection_select helper. I mean come on, there’s no way you can tell me that you can’t love this:

class Continent < ActiveRecord::Base
class Country < ActiveRecord::Base
class City < ActiveRecord::Base

<%= grouped_collection_select(:city, :country_id, @continents, :countries, :name, :id, :name) %>

<select name="city[country_id]">
  <optgroup label="Africa">
    <option value="1">South Africa</option>
<option value="3">Somalia</option>
  </optgroup>
<optgroup label="Europe">
<option value="7" selected="selected">Denmark</option>
    <option value="2">Ireland</option>
</optgroup>
</select>

I have massive Routes

This weekend brought a small, but incredibly useful patch to rake routes by Mike Breen. Now you can filter the listed results by passing in CONTROLLER=foo. That’s. just. awesome. Personally, it’s gotten to the point that my fingers just assume that they are to append the “| grep foo” portion whenever I type rake routes.. apparently I have nerd muscle memory. *sigh*

Short and sweet

I’ll end the BugMash portion here with just a few more commits worth mentioning. Certainly this wasn’t the extent of the BugMash and I could probably fill up another post just as long with even more mashed bugs and features, but it’s gotta end somewhere, right?

  • Rizwan Reza added support for you to define custom RedCloth options via the textilize helper. So, now, textilize("Testing <b>HTML</b>", :filter_html) will actually filter the HTML!
  • You can now redirect_to(User) - note that User is a class not an instance here - as a synonym for redirect_to(users_url). Thanks to Niklas Holmgren for that.
  • Delivered mail items now have the ability to save to disk because of Eric Davis. When using the new :file delivery method, you can even define your own custom :location for directory storage.
  • And finally, it’s not necessarily BugMash-related, but José Valim - among dozens of other commits - added model.destroyed?. This nifty method will return true only if the instance you’re currently looking at has been successfully destroyed.

Now that we’re clear of those, here are a couple of non-BugMash-related topics which were addressed:

A visit to the Oracle

There’s a difference between knowing the path and walking the path. And this week saw some updates to Rails, mostly around testing, adding improved Oracle database support. A large amount of this effort appears to be coming from one man, Raimonds Simanovskis. I know when we talk about databases with Rails, it’s always the big four - SQLite, MySQL, PostgreSQL, and that other one which shall not be named - so it’s nice to get a little more focus the 800lb. gorilla in the room.

This update fixed failing test cases due to offset and limits, empty strings storing as null, numeric results from ActiveRecord.sum, Oracle not utilizing an ‘AS’ keyword on joins, and many more.

AbstractController::Responder

José Valim and Yehuda Katz (and many others, I’m sure) have put in some excellent work in refactoring the Rails renderer. In fact, the majority of the rendering code has come to find a home in a common object, the AbstractController::Responder. Certainly, this may not be its final resting place, but it’s interesting to note that once a lot of the render logic was brought together the core team was able to quickly identify and refactor the logic to see some dramatic speed increases. At one point, Yehuda even mentioned a tested benchmark showing, “10% faster partial rendering,” than Rails 2.3.

I know that in the RailsEnvy podcast I jabbed a few ribs about the amount of time it’s taken to see a Rails 3.0 release, but it’s important to note that these guys are doing some seriously awesome work. I’m seeing extensive testing and benchmarking and very intelligent refactorings. We’ve really got some great things yet to come.

I’m sure I’ve left out several important and/or interesting commits this week. So, I apologize if one of those was yours. I, and the rest of the community, certainly appreciate the effort you all put in this weekend and Rails is certainly better for it. So, thank you, thank you, thank you to all of you BugMashers out there. And, if you missed out on getting your commit in this round, we’re certainly ready to welcome you into the next.

If you prefer to have a shorter audio summary of this content, you should check out a new podcast just launched by Envy Labs, called Ruby5; a 5 minute, twice-weekly podcast covering Ruby and Ruby on Rails news.

Photo: Brooklyn Bridge Virtual Tour by Diego_3336

Community Highlights: IronRuby

As Rubyists migrate from Ruby 1.8 to Ruby 1.9, new Ruby implementations are gaining in maturity. Recently, IBM's Antonio Cangiano wrote an interesting article comparing the performance between Ruby 1.8, 1.9 and IronRuby on Windows which surprised quite a lot of people.

Unfortunately, IronRuby isn't very well known in the Rails community yet.

Here is an interview with Jimmy Schementi, lead developer for IronRuby, to help give you a little insight.

iron ruby logo

Matt: Hi Jimmy, thank you very much for taking the time to answer our questions. Could you please introduce yourself?
Jimmy: Thanks for sending me questions; it's great to see the ever-increasing interest in IronRuby! I live in Seattle and work at Microsoft on a small team making an open-source implementation of Ruby called "IronRuby". I personally split my efforts between making the IronRuby codebase better, integrating IronRuby with .NET-related technologies like Silverlight or ASP.NET MVC, getting our monthly binary releases are in order, discussing IronRuby with the community, and making sure Microsoft's management knows how awesome Ruby is. But I'm definitely not alone on the core team. John Lam fueled the interest of a .NET-Ruby implementation with the RubyCLR project, and started the IronRuby project. Tomas Matousek is the brains behind the IronRuby compiler, and gets credit for all the compiler code and the recent performance gains. Jim Deville is the man keeping IronRuby working with tons of tests and a fantastic test infrastructure. Shri Borde is our manager, and he spends his non-managing time fixing the libraries and hosting the infamous "IronRuby pair-programming" sessions. And of course all the IronRuby contributors over the past two years have been an enormous help.
Matt: As a follow up on a recent blog post, could you tell us know how you learned Ruby and maybe give some advice or an important point not to miss for people wanting to learn Ruby?
Jimmy: I heard about Ruby from my Computer Science professor/advisor Gary Pollice, who taught all the programming language classes at Worcester Polytechnic Institute. I was searching for an expressive programming language for making games, and Ruby was a perfect fit. A couple years later I worked for the same university building a computer-tutoring system called Assistment, where myself and a couple of other people fed up with the Java codebase ported it to Ruby on Rails. It was a success, and http://assistment.org is now a Rails system. That's where I really learned everything about Ruby and became extremely interested in how Ruby worked. I learned the most from Ruby when I had a substantial Ruby project to work on, since I got to see its expressiveness making me more productive on a large scale. I'd still suggest trying to learn Ruby on small things here and there, but you'll really be amazed if you use it for something larger.
Matt: IronRuby certainly looks very interesting, can you run Rails on it?
Jimmy: Yes, at RailsConf 2009 I showed IronRuby running non-trivial Rails applications. IronRuby can run Rails on WEBrick, as well as on the web-server that comes with Windows, IIS. For the database you can use SQLServer Express (which is free), or any .NET based database, like the recent csharp-sqlite port. Here's a detailed post the IronRuby on Rails talk at RailsConf 2009: http://blog.jimmy.schementi.com/2009/05/ironruby-at-railsconf-2009.html.
Matt: Are there any limitations that our readers should be aware of before starting to develop on IronRuby?
Jimmy: The main limitation is that IronRuby does not support any of the C-based Ruby libraries, and only after 1.0 will we consider building an interop layer between the Ruby C API and IronRuby. In the meantime, people have been porting their favorite C-based Ruby libraries over to C# so it can be used from IronRuby, like Hpricot. While this seems like a large limitation, most of the C-based libraries Ruby code depends on have an equivalent API in the .NET framework, which IronRuby has direct integration with, making either using directly or porting really easy. For example, the Rails app I showed at RailsConf did image resizing directly with the System.Windows.Drawing APIs rather than ImageMagick. If your code does not depend on anything outside of the Ruby standard library that is C-based, you should have no problems. Take a look at the documentation for running Rails on IronRuby to make sure things go smoothly: http://ironruby.net/Documentation/Rails.
Matt: What are the pros/cons of using IronRuby versus the standard Ruby (Ruby1.8 or Ruby1.9) on Windows?
Jimmy: IronRuby is a very fast Ruby interpreter/compiler due to our own tricks we pull to make Ruby fast, the tricks the DLR does to make dynamic languages fast, and the CLR's just-in-time compiler which generates very efficient code. We're definitely aiming to be the fastest Ruby implementation on Windows. The most recent performance work we did was only in the core libraries ("Array", "Hash", etc), and that helped IronRuby surpass Ruby 1.8.6 on Windows and gets much closer to Ruby 1.9.1. IronRuby is continuing to investigate ways of gaining performance in each release. IronRuby is also a very 1.8.6 compliant Ruby implementation. There is a "-19" flag for any 1.9 specific features you might need, and a "-20" flag for any Ruby 2.0 features we might have in there, but there are no guarantees on those; we only test the 1.8.6 behavior today. We pass ~85% of the RubySpec test suite, the best test suite for Ruby implementations to verify their correctness. However, the numbers I'm more concerned with are whether specific Ruby libraries' test-suites work. We pass Rails, RubyGems, Rake, and RSpec's test suites at well over 90%, and fix compatibility issues when asked about them, so please let us know if your applications run into any compatibility problems. Other than the limitations that I mentioned in the previous question, you should have no problems. I love people to try running their Rails applications on the latest IronRuby bits hosted on GitHub, and please report any issues you find on http://ironruby.codeplex.com.
Matt: Are they any extra advantages to use IronRuby?
Jimmy: The most notable advantage is that IronRuby works in Silverlight, a subset of the .NET framework which installs as a browser plugin in Mozilla-based browsers (eg. Firefox on Mac and Windows), Webkit-based browsers (eg. Safari on Windows), and IE (on Windows, duh). The Mono project is implementing an open-source version of Silverlight called "Moonlight" so Linux developers can run Silverlight applications, which I talked about at OSCON 2009. This enables you to write Ruby in the browser instead of JavaScript, for controlling HTML or vector graphics. The best place for documentation/examples today is on the Gestalt website, a little portal designed to bring awareness to Ruby and Python in Silverlight: http://visitmix.com/labs/gestalt. The IronRuby website is in flux at the moment, but clearer documentation is on its way. I also built a little Ruby on Rails plugin called "Silverline" to make it really easy to use Silverlight from Rails. Worth checking out if you want to use Ruby as a client scripting language. IronRuby has direct integration with the .NET framework, so anything that is in, or run on, the .NET framework can be used directly from IronRuby. .NET namespaces are exposed as Ruby modules, .NET classes as Ruby classes, and you can call methods on them just like you call Ruby methods. This makes it really easy to build pieces of your system in a static language (if it makes sense to use, like for a high-performance message queue, game engine, etc) and then interact with it through Ruby.
Matt: Why is Microsoft interested in a Ruby project? What advantage do they find in sponsoring such a project?
Jimmy: I see it as a "you scratch my back, I'll scratch yours" situation. Microsoft sponsoring IronRuby helps the Ruby community by making Ruby a first-class language on Windows and .NET, also giving the .NET crowd the choice of using Ruby, and in return the IronRuby project helps promote innovation in the languages that drive Visual Studio purchases (C#, VB.NET, and F#). As a kind-of related side-note: some people feel it's a bad thing that there are so many implementations of Ruby, kind of like MRI is so bad that others had to fix it, but I completely disagree. IronRuby, JRuby, MacRuby, and most of the other implementations accomplish the same thing for their respective communities; building a bridge between Ruby developers and themselves. Rather than needing to recreate MRI, most have been inspired by it and wanted to bring the language to their platform. It's a great thing for the Ruby community because it gives access to more platforms, operating systems, and libraries than any other language. Anyway, back to the question: as an example of how IronRuby has helped language innovation, the next version of C# will now have a "dynamic" keyword, indicating that the variable statically-typed as "dynamic" (=P) should perform dynamic dispatch on any method calls, rather than verify the method call at compile-time. This infrastructure uses the Dynamic Language Runtime directly, so C# can use Ruby objects just like they were defined in C#, or any other dynamic-enabled object.
Matt: How will IronRuby make Rails developer lives easier and what are the plans for the future of IronRuby?
Jimmy: My hope is that IronRuby can benefit existing Rails developers by making Windows a great option to develop and deploy on. By building a Rack adapter specifically for IronRuby and IIS (like I showed at RailsConf), Rails applications can tie directly into the same web-server pipeline that ASP.NET does, significantly reducing the overhead deploying via IIS+FCGI gives you today. This makes deploying Rails applications on IIS just like deploying ASP.NET apps, so system administrators don't have to learn a whole new framework; to them it's just ASP.NET. Then any existing ASP.NET shops who want to offer Rails applications to their customers can, with the same infrastructure and deployment know-how. This is bringing choice to the technologies you choose to deploy on Windows, just like how Microsoft has helped make PHP run well on IIS. The only definite future plans for IronRuby is continue pushing on performance on compatibility, as well as continue supporting the latest version of Silverlight and Mono. 1.0 will be released when the community is happy with the state of those metrics, and future work should be driven by what IronRuby users want. If you start using IronRuby and want a feature either by 1.0 or post 1.0, please post the request to the mailing list or to CodePlex. We have tons of hopes and dreams for what IronRuby can do in the future, so please come help out!
Matt: Is there anything you would like to add or share with the readers?
Jimmy: Thanks to Matt for the interview, and thanks to the readers for getting this far! Go grab the 0.9 release from http://ironruby.net/download, or the latest source from http://github.com/ironruby/ironruby, tell us if you have any problems with it, and we hope you'll help IronRuby get to a 1.0 release.

What's New in Edge Rails: The Hodgepodgery

It’s been quite a while since we’ve had a new Edge Rails post. I’ve really missed them and there have been a lot of changes, both big and small, on the Edge in the time since. In this post I’ll cover a little bit of everything that’s been happening over the past week or so in Rails. Along with this, you should expect to see more frequent and regular updates on all that is currently going on.

Goodbye SQLite dbfile

This is a relatively minor change, unless you still refer to your SQLite database as a dbfile in your database.yml. The dbfile option key is now gone, having been replaced a long time ago by the more standard, database key. So, if you’re suddenly seeing, “No database file specified” errors after you update, this may be your cause.

Кирилица\n祝您好運 ??? We got your Кирилица\n祝您好運 RIGHT HERE

Sava Chankov provided a patch fixing Content-length HTTP response headers being incorrectly calculated with Ruby 1.9 and multi-byte characters. The content length is now calculated based off of the String#bytesize rather than just the String#size. This takes advantage of the multi-byte character support built in to Ruby 1.9, just as long as you remember to always properly tag your multi-byte file with the correct encoding header (i.e. # encoding: utf-8).

That’s not our job

Some spring cleaning, mostly made possible through Rack support, allowed Edge to hand-off some additional responsibilities to the stack. The most interesting of which is now off-loading some of the content-length calculation to your web server rather than being processed directly from within Rails. The largest benefit of this is not so much for the application developers as for you middleware developers. This means that you no longer have to re-calculate the content length when manipulating the body of an HTTP response.

This does not appear to affect the previously mentioned update by Sava, because his fix seems to most largely affect streaming file responses directly through Rails.

We <3 the Hash, and now so does the Cache

Cache control is now being handled by an internal Hash rather than independent string values. Old and busted: headers['Cache-Control'] = 'private', new hotness: response.cache_control[:public] = true. Additional cache_control options include: :public, :max_age, :must_revalidate, and the oh-so-descriptive :extras, which is used mostly for your custom header content.

What time is it!?

Geoff Buesing provided a useful fix for Time, specifically when used in conjunction with ActiveRecord. Now you can save and search ActiveRecord objects using whichever local time zone you like, regardless of what your default time zone is configured for and everything now will just work. You no longer need to be concerned about converting your user’s local time into your default application time or vice versa.

It’s STATE of the art

ActiveRecord now has easy access to ActiveModel’s StateMachine implementation. I don’t know about you, but somehow I always seem to find a way to bring state machines into my Rails applications, and now building in - even fairly complex - state machines just got a whole lot easier.

For an example of ActiveModel::StateMachine and to get an idea of how you might use it, check out my more detailed blog post over at Envy Labs.

Front. Back. Side to side.

Paul Gillard committed a patch which now allows for both custom suffixes (which really isn’t new) and prefixes (omg THAT IS!) on your ActiveRecord attributes. This gives you access to attribute_method_prefix, attribute_method_suffix, and now attribute_method_affix. While it may sound a little silly, check this out:


class Person < ActiveRecord::Base
  attribute_method_affix :prefix => 'me_mateys_', :suffix => '_is_in_pirate?'
  
  private
  
  def me_mateys_attribute_is_in_pirate?(attr)
    send(attr).to_s =~ /\bYAR\b/i
  end
end

person = Person.find(1)
person.name                               #=> 'Paul Gillard'
person.profession                         #=> 'A Pirate, yar!'
person.me_mateys_name_is_in_pirate?       #=> false
person.me_mateys_profession_is_in_pirate? #=> true

Okay, well, that’s still a little silly, but hopefully you get the idea and can think of a few usage scenarios of your own. So, basically, now you can add your own dynamic ActiveRecord methods that can potentially affect any or all of it’s attributes.

Clean yourself up

Paul Gillard posted another useful patch, utilizing that one previously mentioned, to now provide us all with this syntactic sugar: reset_attribute! And he even provided us with a pirate of his own to show off this new bounty:


pirate = Pirate.create!(:catchphrase => 'Yar!')
pirate.catchphrase = 'Ahoy!'
pirate.reset_catchphrase!
assert_equal "Yar!", pirate.catchphrase
assert_equal Hash.new, pirate.changes
assert !pirate.catchphrase_changed?

Nobody likes a dirty pirate.