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
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request