Module: CastAttribute
- Defined in:
- lib/cast_attribute.rb
Overview
CastAttribute is an extension to ActiveRecord for casting attributes to different types. For example, let’s say you have a model called Product, and some of your products have Japanese characters in their names, so you want to use your UnicodeString class with your Product model. You can do this with CastAttribute like so:
class Product < ActiveRecord::Base
cast_attribute :name, :as => UnicodeString
end
Now the name
attribute on your Product model will be an instance of UnicodeString:
>> Product.first.name.class
=> UnicodeString
Caveats
CastAttribute will not install itself into ActiveRecord::Base unless explicitly instructed to:
CastAttribute.install!
CastAttribute defines accessor methods for the attributes you want to cast. (I.e., in the example above, cast_attribute defines two instance methods in Product: name
and name=
.) If you want to add any functionality to a cast attribute’s accessors, you must use method chaining. Sorry.
Class Method Summary collapse
-
.included(base) ⇒ Object
:nodoc:.
-
.install! ⇒ Object
Installs CastAttribute into ActiveRecord::Base.
Instance Method Summary collapse
-
#cast_attribute(name, *options) ⇒ Object
Causes the values of the attribute specified by
name
to be instances of the class specified in the:as
key ofoptions
.
Class Method Details
.included(base) ⇒ Object
:nodoc:
37 38 39 |
# File 'lib/cast_attribute.rb', line 37 def self.included(base) # :nodoc: base.extend(self) end |
.install! ⇒ Object
Installs CastAttribute into ActiveRecord::Base.
31 32 33 34 35 |
# File 'lib/cast_attribute.rb', line 31 def self.install! ActiveRecord::Base.class_eval do include CastAttribute end end |
Instance Method Details
#cast_attribute(name, *options) ⇒ Object
Causes the values of the attribute specified by name
to be instances of the class specified in the :as
key of options
. For example, to make the title
attribute of a Book model use UnicodeString instead of the regular String:
class Book < ActiveRecord::Base
cast_attribute :title, :as => UnicodeString
end
You can cast more than one attribute at a time like so:
class Book < ActiveRecord::Base
cast_attribute :title, :summary, :as => UnicodeString
end
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/cast_attribute.rb', line 56 def cast_attribute(name, *) # Extract and check arguments. names = [name] + = names.pop unless .is_a?(Hash) raise TypeError, 'last argument must be a Hash' end if names.empty? raise ArgumentError, 'no attribute names specified' end klass = .delete(:as) unless .empty? raise ArgumentError, "unknown key(s): `#{.keys.join("', `")}'" end unless klass.is_a?(Class) raise TypeError, 'value of :as option must be a Class' end # Create attribute reader and writer methods. names.each do |name| unless columns_hash[name.to_s] raise ArgumentError, "#{self} has no `#{name}' attribute" end class_eval <<-EOS def #{name} @cast_attribute_#{name} ||= #{klass}.new(read_attribute(:#{name})) end def #{name}=(value) @cast_attribute_#{name} = nil super end EOS end end |