Metafy

Metafy is a Gem for Rails 3 that makes it possible to easily add dynamic attributes to any ActiveRecord model. These lightweight, meta attributes work just like normal database column attributes on your ActiveRecord model and are fully searchable (i.e. you can find records by values contained in these dynamic attributes).

The inspiration for Metafy actually came through the usermeta and postmeta mechanisms that WordPress makes available to developers. Metafy expands on this idea and allows developers to create meta mechanisms for any model in Rails.

Download

Metafy is an open source gem released under the MIT license and it’s available for download on RubyGems.org or it’s repository on GitHub.

Installation

To apply Metafy to any ActiveRecord model, follow these simple steps:

  1. Install
    • Add to Gemfile: gem ‘metafy’
    • Install required gems: bundle install
  2. Add the ‘mattrs’ table to your database
    • Create migration: rails g metafy
    • Migrate your database: rake db:migrate
  3. Add metafied attributes to any of your ActiveRecord models using the metafy class method:
    • Add to app/models/model.rb: metafy :attribute_name

Example

Say you had a table named “users”:

  mysql> desc users;
  +----------------+--------------+------+-----+---------+----------------+
  | Field          | Type         | Null | Key | Default | Extra          |
  +----------------+--------------+------+-----+---------+----------------+
  | id             | int(11)      | NO   | PRI | NULL    | auto_increment |
  | username       | varchar(255) | YES  | MUL | NULL    |                |
  | email          | varchar(255) | YES  | MUL | NULL    |                |
  | created_at     | datetime     | YES  |     | NULL    |                |
  | updated_at     | datetime     | YES  |     | NULL    |                |
  +----------------+--------------+------+-----+---------+----------------+

And you wanted some lightweight, dynamic fields associated with the User model but didn’t necessarily want them in the schema then you could add them as meta attributes using metafy like so:

  # app/models/user.rb
  class User < ActiveRecord::Base
    metafy :first_name, :last_name,:gender, :country, :language
  end

Now you can do things like:

  >> user = User.meta_where( :first_name => 'Bevis' ).first
  >> user.first_name = 'Larry'
  >> user.save
  >> user.first_name
    => 'Larry'

OR create a new record with meta attributes:

  >> user = User.new :first_name => 'Jerry', :last_name => 'Johnson'
  >> user.save

OR select using the meta_where scope:

  >> num_johnsons = User.meta_where( :last_name => 'Johnson' ).count

OR select & order using standard rails relations:

  >> num_johnsons = User.where( :m_country => { :meta_value => 'Canada' } ).order( 'm_last_name.meta_value ASC' )

OR chain where with meta_where:

  >> users = User.where( 'users.email LIKE "%@gmail.com"' ).meta_where( :language => "French" )

Why would I want to use this Gem instead of just adding more database columns?

Well, there isn’t much difference functionally between a normal database colunn and a meta attribute. But there may be sometimes when you want to add a more dynamic, lightweight attribute that doesn’t clutter your schema. That’s when you’d use metafy.