Skip to content


Subversion checkout URL

You can clone with
Download ZIP
Add attributes to Ruby objects
Failed to load latest commit information.
test Make sure associations still return an empty Array even if autoload_a…
.gitignore Initial commit
.ruby-version Bump ruby version
Gemfile Initial commit
LICENSE.txt updated readme
Rakefile Make test work even if test isn't on your global load path
attribution.gemspec Make sure associations still return an empty Array even if autoload_a…


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
Something went wrong with that request. Please try again.