Custom ActiveRecord Attribute Serialization

by: Jeff Kreeftmeijer | posted: March 9th, 2011

Rails 3.1

As you might know already, ActiveRecord lets you store serialized objects by using serialize in your model:

Ruby - app/models/user.rb
  class User < ActiveRecord::Base
    serialize :interests
  end

These serializeable attributes can then be set as any Ruby type such as an array:

rails console
user = User.create!(:interests => ['dinosaurs', 'lasers'])
user.reload.interests # => ["dinosaurs", "lasers"]

Under the hood, this array is automatically converted to YAML. You won’t notice this unless you check what’s being inserted into your database:

log/development.log
INSERT INTO "users" ("updated_at", "interests", "created_at") VALUES ('2011-03-05 13:14:05.054192', '---
- dinosaurs
- lasers
', '2011-03-05 13:14:05.054192')

Using arbitrary objects

Aaron Patterson recently did some work for Rails 3.1 which allows you to use arbitrary objects to serialize your attributes, all they need to do is respond to load and dump. This allows you to specify a custom encoding for your models serialize fields. For example, here is what a Base64 encoding might look like:

Ruby - app/models/user.rb
class User < ActiveRecord::Base
  class Base64
    def load(text)
      return unless text
      text.unpack('m').first
    end

    def dump(text)
      [text].pack 'm'
    end
  end

  serialize :bank_account_number, Base64.new
end

Just like the default YAML serialization, ActiveRecord won’t bother you with any serialized data, unless you check the SQL query:

rails console
user = User.create!(:bank_account_number => "0000001 00000011 0000001 00000011")
user.reload
user.bank_account_number # => "0000001 00000011 0000001 00000011"
log/development.log
INSERT INTO "users" ("updated_at", "bank_account_number", "created_at") VALUES ('2011-03-05 17:12:01.459862', 'MDAwMDAwMSAwMDAwMDAxMSAwMDAwMDAxIDAwMDAwMDEx\n', '2011-03-05 17:12:01.459862')

Just remember, YAML serialization is still used by default, but creating your own serialization object is as simple as load and dump.

Links:

Custom serialization in action video

The Rails commits here and here