Skip to content
Add attributes to Ruby objects
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.


Attribution is a gem to allow you to define attributes for a Ruby object so that getters and setters will be defined that handle typecasting. It also allows you to define associations between objects in an ActiveRecord-style way.


Add this line to your application's Gemfile:

gem 'attribution'

And then execute:

$ bundle

Or install it yourself as:

$ gem install attribution


You can define attributes like this:

class Book
  include Attribution

  integer :id
  string :title
  decimal :price
  date :published_on
  boolean :ebook_available
  boolean :used
  float :shipping_weight
  time :created_at
  time :updated_at
  time_zone :time_zone

  has_many :chapters

class Chapter
  include Attribution

  integer :number
  string :title
  integer :page_number

  belongs_to :book

And then you can pass in a Hash or a String of JSON to initialize the object:

json = %{{
  "id": 1,
  "title": "Rework",
  "price": "22.00",
  "published_on": "March 9, 2010",
  "ebook_available": "yes",
  "used": "no",
  "shipping_weight": "14.4",
  "created_at": "2013-02-20 05:39:45 -0500",
  "updated_at": "2013-02-20T05:40:37-05:00",
  "time_zone": "Eastern Time (US & Canada)",
  "chapters": [
      "number": "1",
      "title": "Introduction",
      "page_number": "1"
      "number": "2",
      "title": "Takedowns",
      "page_number": "7"
      "number": "3",
      "title": "Go",
      "page_number": "29"

book =

The object is populated based on the data, the values are converted into the type defined by the attribute:

=> 1
>> book.title
=> "Rework"
>> book.price
=> #<BigDecimal:7f82dfe9d018,'0.22E2',9(18)>
>> book.published_on
=> Tue, 09 Mar 2010
>> book.ebook_available?
=> true
>> book.used?
=> false
>> book.shipping_weight
=> 14.4
>> book.created_at
=> 2013-02-20 05:39:45 -0500
>> book.updated_at
=> 2013-02-20 05:40:37 -0500
>> book.time_zone
=> GMT-05:00 Eastern Time US  Canada

Also, the association is populated with an array of objects:

>> book.chapters.size
=> 3
>> book.chapters[2].page_number
=> 29

The reciprocating association is populated as well:

>> book.chapters[2].book.title
=> "Rework"

You can access the values of all attributes as a hash:

>> pp book.attributes
 :published_on=>Tue, 09 Mar 2010,
 :created_at=>2013-02-20 05:39:45 -0500,
 :updated_at=>2013-02-20 05:40:37 -0500,
 :time_zone=>(GMT-05:00) Eastern Time (US & Canada)}

You can also add any arbitrary metadata to any attribute:

class Book
  include Attribution

  decimal :price, :required => true, :doc => "Price in USD", :whatever => "why not?"

And retrieve that metadata any time:

>> Book.attributes
=> [{:required=>true, :doc=>"Price in USD", :whatever=>"why not?", :name=>:price, :type=>:decimal}]

Attribution also has a module to make any object act more like a model:

require 'attribution/model'
class Book
  include Attribution::Model

By using Attribution::Model, your object will:

  • Have an id that is an integer
  • Implementation for equality and hash based on the id
  • Have a created_at that is a time
  • Have an updated_at that is a time
  • Include ActiveModel::Validations

You can define validations in the standard way you do when using ActiveModel::Validations:

class Book
  include Attribution::Model

  belongs_to :author

  string :title

  validates :title, :presence => true
  validates :title, :uniqueness => true
  validates :title, :format => { :with => /^\w/, :message => "must start with a letter" }

Or, more concisely, you can define the validation as part of the attribute definition:

class Book
  include Attribution::Model

  belongs_to :author

  string :title, :required => true,
                 :unique => true,
                 :format => { :with => /^w/, :message => "must start with a letter" }


  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request
You can’t perform that action at this time.