6 January 2013 · About 3 minutes read

Rails 3: Storing Model Metadata Attributes with ActiveRecord::Store

I recently discovered the excellent ActiveRecord store method whilst researching the best-practice for storing optional, flexible metadata against a record. store lets you keep simple key/value data into a single text column on your model.

By declaring stored attributes on your model, ActiveRecord will automatically generate the appropriate setter/accessor methods, and validations work just as you’d expect.

# db/migrate/create_cars.rb

# ...

create_table do |t|

  t.references :model

  t.references :manufacturer

  t.text :metadata # Note metadata is just a text column

  t.timestamps

end

# app/models/car.rb

class Car < ActiveRecord::Base

  belongs_to :model

  belongs_to :manufacturer

  # Manufacturer and Model are 'real', database-backed attributes

  attr_accessor :model_id, :manufacturer_id, :colour, :size, :notes, :product_url

  store :metadata, :accessors => [:colour, :size, :notes, :product_url]

  # Database-backed attributes

  validates :model, :presence, :presence => true

  validates :manufacturer, :presence => true

  # Metadata stored attributes

  validates :colour, :presence => true

  validates :size, :presence => true, :inclusion => { :in => %w(small medium large) }

  validates :product_url, :format => { :with => /^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/ }

end

Note that the metadata is just a text column. Rails will automatically serialise the hash into this column.

With our Car model defined, and its metadata attributes declared with store, we can use them in just the same way as normal, database-backed attributes:

car = Car.new

car.model = CarModel.first

car.manufacturer = Manufacturer.first

car.colour = "Red"

car.size = "medium"

car.product_url = "http://www.example.com/"

car.save

# => true

car.colour

# => "red"

car.size

# => "medium"

Pros and Cons

The biggest advantage to this type is store is it provides a flexible data schema. This is perfect for storing non-indexed metadata about a model, and a use-case that often crops up when building apps. It provides a compromise between common relational databases (such as MySQL and PostgreSQL) and the flexibility of NoSQL databases such as MongoDB and CouchDB. In practical use, it means attributes can quickly be added to a model without the need to perform any migrations on the database schema.

A possible disadvantage is that stored attributes can not be indexed or used in queries (as they have no corresponding database column). For example, you could not call Car.where(:colour => "red"). However, as Garry Tan points out in his post, if this becomes a requirement in the future, you could always add a database-column to the schema at a later date, and just move the data at that time.

Helpful post? Let me know on Twitter.

References

  1. http://axonflux.com/one-of-my-favorite-additions-to-rails-3-activ

Learn how to keep your Rails apps fast, secure and running in top condition.

The Ruby and Rails worlds move fast, so it can feel like no time at all before your app starts to feel left behind.

Slow pages, memory, new gems, a constant stream of security patches, changing third-party APIs, and growing demands on your server's resources all work tirelessly against your app.

While your app launched with a strong foundation— the latest gems, employing best practices, and developing a thorough test suite—it needs constant attention and maintenance to keep running in top condition.

In Keep Your Ruby on Rails App Healthy, you'll learn about the tools and techniques for keeping your Ruby on Rails app running smoothly, and how to apply them to your apps.

The course delivers a range of practical and actionable lessons to enhance and protect your app right away, from simple, quick–win optimisations and setting up thorough monitoring to reviewing your site's performance, and checking your code against security vulnerabilities current best practices.

“I really enjoyed the book. A lot of quick wins for me to implement and makes me realise I can do more with guard.” –– Ben (@r0_0tKat)

Keep Your Ruby on Rails App Healthy is available as both an email course, and as a premium download edition.

The email course is split up into 7 lessons, delivered to your inbox over the course of a month.

The premium edition is available for instant download in PDF, ePub and Mobi (Kindle) format.

Start Email Course Buy Premium $9 (plus EU VAT)

programming tips activerecord rails-3 ruby
Chris Blunt
Chris Blunt @cblunt
Chris is the founder of Plymouth Software. As well as code and business, he enjoys being a Dad, swimming, and the fine art of drinking tea.