Notes from Reading ActiveRecord::Base

by Charles Max Wood on March 16, 2010

I’ve been trying to read more code lately and figured that I’d be best served by reading code I use frequently. Here are some notes of things I gathered from reading the ActiveRecord base.rb file.

1. Handling large query parameter sets

You can do safe queries by specifying your query arguments as a has, rather than an array using ‘?’.

Company.find(:first, :conditions => [
  "id = :id AND name = :name AND division = :division AND created_at > :accounting_date",
  { :id => 3, :name => "37signals", :division => "First", :accounting_date => '2005-01-01' }
])

2. Querying ranges

Student.find(:all, :conditions => { :grade => 9..12 })

This will yield a “BETWEEN 9 AND 12″ in the query string

Student.find(:all, :conditions => { :grade => [9,11,12] })

This will yield an “IN (9, 11, 12)” in the query string

3. [] notation on ActiveRecord objections

I’ve used [] on ActiveRecord objects to get the id from the attributes hash, rather than the object_id, which can pull some useless number off of the ruby object. What I didn’t know was that the following sets were calls to the same method:

@object[:attribute]
@object.read_attribute(:attribute)

and

@object[:attribute]= "abc"
 @object.write_attribute(:attribute, "abc").

4. Attribute presence checks

You can test if an attribute is nil or blank by doing the normal method call with an appended ‘?’. Here’s an example from the codebase:

user = User.new(:name => "David")
user.name? # => true

anonymous = User.new(:name => "")
anonymous.name? # => false

5. Attributes before they are typecast

A call like this will give you back the raw data before it is cast to whatever is expected (like an integer).

@object.id_before_type_cast

6. Find or initialize by

This is just like ActiveRecord::Base#find_or_create_by… methods, except it calls #new instead of #create.

7. Serializing Arrays, Hashes, and Objects

I didn’t realize that you could serialize objects under other objects in ActiveRecord. You can. It serializes your object or hash to YAML and saves it as text in the database.

  class User  { "background" => "black", "display" => large })
  User.find(user.id).preferences # => { "background" => "black", "display" => large }

8. Protected attributes

Protected attributes are attributes protected from mass assignment. In other words, if your :name attribute is protected, then the following code will initialize a User without setting the :name attribute.

class User  "George")
user.name #=> nil

{ 6 comments… read them below or add one }

Craig P Jolicoeur March 16, 2010 at 11:36 am

Nice notes. I personally didn’t know about the option of using a hash for conditional query params

Reply

Sleeptillseven March 16, 2010 at 11:01 pm

Thanks. That’s gonna save my head while digging in the AR jungle.

Reply

Sammy March 17, 2010 at 12:18 pm

> You can test if an attribute is nil or blank by doing the normal method call with an appended ‘?’

Boolean attributes will return false if value is false or nil.

Personally I prefer #blank? and #present? instead of this magic.

Reply

François Beausoleil March 17, 2010 at 3:27 pm

You should also mention #attr_accessible, which is a better for of #attr_protected.

Reply

keikun17 March 17, 2010 at 7:54 pm

sweet. everything is known to me except for #1

Reply

Nicolas Blanco March 18, 2010 at 5:15 am

You should never use attr_protected (which is blacklist technique) but attr_accessible instead (whitelist). IMHO, attr_protected should be deleted from AR.

Reply

Leave a Comment

{ 3 trackbacks }

Previous post:

Next post: