1. ActiveRecord

There is new bind-style variable interpolation for the condition arrays that uses the adapter’s quote method.

Before:

find_first([ "user_name = '%s' AND password = '%s'", user_name, password ])
find_first([ "firm_id = %s", firm_id ]) # unsafe!

After:

find_first([ "user_name = ? AND password = ?", user_name, password ])
find_first([ "firm_id = ?", firm_id ])

This takes care of wrapping the appropriate quotes around each attribute, in addition to sanitizing the input.

There is also a named bind-style variable interpolation that is used like so:

Person.find_first(
  ["id = :id and first_name = :first_name", 
  { :id => 5, :first_name = "bob' or 1=1" }])

Please update to the new bind style if you use the printf style in your application since its much more secure and can be subject to future optimization when when more database drivers support prepared statements.

If you’d like to do a regular expression search using the ’search term’ notation, such as with mysql, this can be accomplished like so:

find_all([ "username LIKE ?", "%#{username)%" ])

Overview

Validation has taken a big leap forward in simplicity and capability. With easy 1 line methods, you decorate your model with various constraints. Here’s an overview of the macros available:

  • validates_confirmation_of
  • validates_acceptance_of
  • validates_presence_of
  • validates_length_of
  • validates_uniqueness_of
  • validates_format_of
  • validates_inclusion_of

validates_presence_of

validates_presence_of is a new macro style method which encapsulates the process of defining a validate method and setting errors.add_on_empty to attributes.

Before:

def validate
  errors.add_on_empty %w{first_name last_name username}
end

After:

class User < ActiveRecord::Base
  validates_presence_of :first_name, :last_name, :username
end

validates_acceptance_of

validates_acceptance_of encapsulates the pattern of wanting to validate the acceptance of a terms of service box (or some such agreement). Example:

Model:

class Person < ActiveRecord::Base
  validates_acceptance_of :terms_of_service
  validates_acceptance_of :eula, :message => "must be abided by" 
end

View:

<%= check_box "person", "terms_of_service" %>

Note that the terms_of_service attribute is entirely virtual. No database column is needed. This check is performed both on create and update.

The :message option allows you to specify a custom error message (default is: “must be accepted”)

If you want to restrict the validation to just one of the two situations you can include the :on option, as in:

class Person < ActiveRecord::Base
  validates_acceptance_of :terms_of_service, :on => :create
end

validates_confirmation_of

validates_confirmation_of encapsulates the pattern of wanting to validate a password or email address field with a confirmation. Example:

Model:

class Person < ActiveRecord::Base
  validates_confirmation_of :user_name, :password, :on => :create
  validates_confirmation_of :email_address, :message => "should match confirmation" 
end

View:

<%= password_field "person", "password" %>
<%= password_field "person", "password_confirmation" %>

The person has to already have a password attribute (a column in the people table), but the password_confirmation is virtual. It exists only as an in-memory variable for validating the password. This check is performed both on create and update.

The :message option allows you to specify a custom error message (default is: “doesn’t match confirmation”)

validates_uniqueness_of

validates_uniqueness_of validates whether the value of the specified attributes are unique across the system. Useful for making sure that only one user can be named “davidhh”.

Model:

class Person < ActiveRecord::Base
  validates_uniqueness_of :user_name
end

View:

<%= text_field "person", "user_name" %>

When the record is created, a check is performed to make sure that no record exist in the database with the given value for the specified attribute (that maps to a column). When the record is updated, the same check is made but disregarding the record itself.

The :message option allows you to specify a custom error message (default is: “has already been taken”)

validates_inclusion_of

This validates that an attribute is contained within something. The something can be an Array, a Range, a String, or anything else sporting the include? method.

Model:

class Person < ActiveRecord::Base
  validates_inclusion_of :gender, :in => ['m','f']
  validates_inclusion_of :temperature, :in => -273..5000
end

validates_length_of

This method specializes in validating string sizes. It supports checking if a string is too small, too big, an exact number, or within a range.

Model:

class Person < ActiveRecord::Base
  validates_length_of :first_name, :maximum=>50
  validates_length_of :alphabet, :is=>26
  validates_length_of :initials, :within=>2..3
end

validates_format_of

This validation performs Regular Expression checks.

class Person < ActiveRecord::Base
  validates_format_of :email, :with => /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/
end
Associations have improved. They will now attempt to automatically require the class they need. So instead of repeating yourself with:
require 'comment'

class Post < ActiveRecord::Base
  has_many :comments
end

You can now leave out the explicit require and just rely on Active Record to follow your association specification and do the require:

class Post < ActiveRecord::Base
  has_many :comments
end

For this to work comments has to be in a file called comments.rb. Note that this does not work for Single table inheritance. You still need to require the parent class. ( please use require_dependency see below…)

WRITE INFO ABOUT acts_as_list AND acts_as_tree