lib/representable/coercion.rb in representable-1.5.3 vs lib/representable/coercion.rb in representable-1.6.0

- old
+ new

@@ -1,17 +1,42 @@ require "virtus" module Representable::Coercion + class Coercer + include Virtus + + def coerce(name, v) # TODO: test me. + # set and get the value as i don't know where exactly coercion happens in virtus. + send("#{name}=", v) + send(name) + end + end + # separate coercion object doesn't give us initializer and accessors in the represented object (with module representer)! + def self.included(base) base.class_eval do - include Virtus extend ClassMethods + # FIXME: use inheritable_attr when it's ready. + representable_attrs.inheritable_array(:coercer_class) << Class.new(Coercer) unless representable_attrs.inheritable_array(:coercer_class).first end + end module ClassMethods - def property(name, args={}) - attribute(name, args[:type]) if args[:type] # FIXME (in virtus): undefined method `superclass' for VirtusCoercionTest::SongRepresenter:Module - super(name, args) + def property(name, options={}) + return super unless options[:type] + + representable_attrs.inheritable_array(:coercer_class).first.attribute(name, options[:type]) + + # By using :getter we "pre-occupy" this directive, but we avoid creating accessors, which i find is the cleaner way. + options[:decorator_scope] = true + options[:getter] = lambda { |*| coercer.coerce(name, represented.send(name)) } + options[:setter] = lambda { |v,*| represented.send("#{name}=", coercer.coerce(name, v)) } + + super end + end + + def coercer + @coercer ||= representable_attrs.inheritable_array(:coercer_class).first.new end end