Extended Attributes
Add custom behavior to your model attributes in ActiveRecord
How often do you have to have an instance method implemented in a model but only to work with just 1 attribute?
class User < ActiveRecord::Base
def first_name
name.split(' ').first
end
def about_in(format = :plain)
case format
when :plain; about
when :html; RDiscount.new(about).to_html
end
end
end
But attributes are also objects at the end of the day right? Should the first_name method belong to the attribute name? With this gem you can extend your attribute by mixing modules with them or having attribute specific methods defined on them. Just like our relationship objects.
In your Gemfile
gem 'extended_attributes'
$ bundle install
and now you can do:
class User < ActiveRecord::Base
extend_attribute :name do
def first
split(' ').first
end
def last
split(' ').last
end
end
end
And you will be able to do:
user = User.find(:first)
user.name # John Anderson
user.name.first # John
user.name.last # Anderson
Additionally, you can also have modules exteded on the attributes
module MarkdownMethods
def to_html
RDiscount.new(self).to_html # requies rdiscount gem
end
end
class User < ActiveRecord::Base
extend_attribute :about, :extend => MarkdownMethods
end
And...
@user.about # _This text should appear italic_
@user.about.to_html # <p><em>This text should appear italic</em></p>\n
Another example from examples
folder
require 'net/http'
require 'uri'
require 'json'
module SocialProfiles
def to_facebook
"http://www.facebook.com/#{self}"
end
def to_twitter
"http://www.twitter.com/#{self}"
end
def on_twitter?
url = "http://api.twitter.com/1/users/show.json?screen_name=#{self}"
json = Net::HTTP.get_response(URI.parse(url)).body
JSON.parse(json)['error'].nil?
end
end
class User < ActiveRecord::Base
extend_attribute :username, :extend => SocialProfiles
end
And...
@user.username # chirantan
@user.username.to_twitter # http://www.twitter.com/chirantan
@user.username.on_twitter? # true
@user.username.to_facebook # http://www.facebook.com/chirantan
Why?
Extending attributes adds modularity to your design, better object orientation and makes interfaces clean.
Dealing with Fixnum
Fixnums cannot have singleton methods. Thus, if you try to extend an attribute that is a Fixnum, the whole behavior will be include
d on Fixnum class, which means that the same behavior will be available on all instances of Fixnum throughout your application. So be careful with them.
Note
This gem was developed because I liked it and it serves my purpose. Feel free to add to it. I’ll be happy to accept pull requests.