module Ixtlan module Babel module ModelFilter def self.included( model ) model.extend( ClassMethods ) end def respond_to? name @model.respond_to? name end def method_missing( name, *args, &block ) @model.send( name, *args, &block ) end def to_json to_data.to_json end def to_yaml to_data.to_yaml end def to_data case @model when Array @model.collect do |m| replace( m ).to_hash end else to_hash end end def serializers=( map ) @map = map end def serialize( data ) if @map && ser = @map[ data.class.to_s ] ser.call( data ) else data end end def to_hash result = {} self.class.attributes.each do |k,v| if v filter = v.is_a?( Array ) ? v[ 0 ] : v filter.serializers = @map model = @model.send( k ) result[ k ] = filter.replace( model ).to_data if model else result[ k ] = serialize( @model.send( k ) ) end end result end def initialize( model = nil, map = nil ) super() @map = map replace( model ) end def replace( model ) @model = model self end module ClassMethods def attribute( name, type = nil ) attributes[ name.to_sym ] = new_instance( type ) end def attributes @attributes ||= (superclass.attributes.dup rescue nil) || {} end def new_instance( type ) case type when Array [ type[ 0 ].new ] when NilClass nil else type.new end end end end end end # class User # include Babel::ModelFilter # attribute :id # end # class A # include Babel::ModelFilter # attribute :id # attribute :created_at, Array[User] # attribute :updated_at # attribute :modified_by, User # end # class B # attr_accessor :id, :created_at, :updated_at, :name, :modified_by # end # b = B.new # b.id = 123 # require 'date' # b.updated_at = DateTime.now # b.name ='bla' # b.modified_by = B.new # b.modified_by.id = 432 # b.modified_by.name = 'asd432' # b.created_at = [ b, b.modified_by] # require_relative 'factory' # a = A.new( b, Babel::Factory::DEFAULT_MAP ) # p a # p a.to_hash # p a.id