In association with heise online


Developers will find building their own authentication system much easier with Rails 3.1's #has_secure_password method. This particular method requires that the user model has a database attribute of "password_digest", which stores a password encrypted by BCrypt. Validations for the presence of password and its confirmation are included in the #has_secure_password method.

Consider the following example:

# create_users migration
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :email
t.string :password_digest
# ... and so on ...

# app/models/user.rb
class User < ActiveRecord::Base

# rails console

ruby-1.9.2-p180 :001 > user = => "",
:password => "really secure password!")
ruby-1.9.2-p180 :002 >
=> true
ruby-1.9.2-p180 :003 > user.authenticate("wrong password")
=> false
ruby-1.9.2-p180 :004 > user.authenticate("really secure password!")
=> user

In this example, a model (User) which #has_secure_password has the #authenticate method added to it, which is used to check the validity of the user's password against a string supplied when calling the method. This method either returns false, or the user object if the password was correct.

While this addition isn't as full-featured as an authentication system such as AuthLogic or Devise, it allows the developer to create a simple authentication system from scratch, and add features to it as needed.

Identity Map

In previous versions of Rails, if a developer retrieved two identical records from the database and assigned them into two different variables, two separate objects would be created in memory. This can have serious performance implications in certain circumstances. Rails 3.1 introduces a feature called "Identity Map" which ensures that, in cases where identical objects are retrieved from the database, the second value created in memory is simply a reference to the first, and not another full object.

For example, if Identity Map is enabled, the following scenario will prevent a second object from being created in memory:

# in a rails console
ruby-1.9.2-p180 :001 > u1 = User.find(1)
=> #<User ... >
ruby-1.9.2-p180 :001 > u2 = User.find(1)
=> #<User ... >
ruby-1.9.2-p180 :001 > u1.object_id == u2.object_id
=> true

# With Identity Map disabled:
ruby-1.9.2-p180 :001 > u1.object_id == u2.object_id
=> false # two identical objects in memory - the second one is just
# wasting space!

Identity Map is disabled by default in Rails 3.1 because of some inconsistencies involving model relationships that are planned to be "ironed out" in a future release. Anyone wanting to use Identity Map should carefully examine the implications listed in the comments of the source code, and decide whether their application can use it safely and without too much refactoring overhead.

In Summary

Rails 3.1 has many useful features aimed at making its performance better in production, as well as simplifying the development process through better organisation and by providing better tools to the developer.

Rails 3.1 also contains additional features developers may find useful:

More Information

Should I Upgrade My App?

Upgrading can be a bit of a mixed bag – some things will need lots of refactoring, and others will simply work without any changes. Developers considering an upgrade should decide whether or not using the latest framework would be worth the development time and effort required. For example, Rails 3.1 will officially remove support for the :conditions hash option in Model#find, which will be used in the vast majority of queries in a 2.3.x application, requiring many changes to your application's codebase.

Both the 2.3.x and 3.0 branches of Rails will likely be maintained with security updates and bug fixes for quite a while, making upgrading less of a necessity and more of an opportunity. However, updates and bug fixes will inevitably cease for these versions one day, and the longer you wait before upgrading your application, the more work you will have to do (in theory) to update a codebase based on 2.3.x to, for example, 4.0 when it releases.

Upgrading can usually be done over the course of one or two consecutive sprints in most development cycles. For example, you may take your existing 2.3.x application to Rails 3 in one sprint (or set thereof), which will allow you to refactor many parts of the codebase, but maintain compatibility for older ActiveRecord usage (albeit deprecated). A secondary sprint could be done later, after adding additional features to keep users happy, for upgrading to 3.1. That sprint would likely involve changing a multitude of ActiveRecord usages, database migrations, and other details that may have been too numerous to handle in combination with changes from 2.3.x to 3.0.

J. Austin Hughey (@jaustinhughey) is a web applications engineer from Texas (United States). After building web applications in PHP/MySQL for six years, in 2007 he made the switch to Ruby and hasn't really looked back.

Print Version | Permalink:
  • Twitter
  • Facebook
  • submit to slashdot
  • StumbleUpon
  • submit to reddit

  • July's Community Calendar

The H Open

The H Security

The H Developer

The H Internet Toolkit