Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Add attributes to Ruby objects
Ruby
Failed to load latest commit information.
lib
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
README.md 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…

README.md

Attribution

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.

Installation

Add this line to your application's Gemfile:

gem 'attribution'

And then execute:

$ bundle

Or install it yourself as:

$ gem install attribution

Usage

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
end

class Chapter
  include Attribution

  integer :number
  string :title
  integer :page_number

  belongs_to :book
end

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 = Book.new(json)

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

>> book.id
=> 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
{:id=>1,
 :title=>"Rework",
 :price=>#<BigDecimal:7f87db1f0b48,'0.22E2',9(18)>,
 :published_on=>Tue, 09 Mar 2010,
 :ebook_available=>true,
 :used=>false,
 :shipping_weight=>14.4,
 :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?"
end

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
end

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" }
end

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" }
end

Contributing

  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.