lib/disposable/composition.rb in disposable-0.0.9 vs lib/disposable/composition.rb in disposable-0.1.0

- old
+ new

@@ -1,78 +1,41 @@ -require 'forwardable' - module Disposable - # Composition delegates accessors to models as per configuration. + # Composition allows renaming properties and combining one or more objects + # in order to expose a different API. + # It can be configured from any Representable schema. # - # Composition doesn't know anything but methods (readers and writers) to expose and the mappings to - # the internal models. Optionally, it knows about renamings such as mapping `#song_id` to `song.id`. + # class AlbumTwin < Disposable::Twin + # property :name, on: :artist + # end # - # class Album - # include Disposable::Composition - # - # map( {cd: [[:id], [:name]], band: [[:id, :band_id], [:title]]} ) + # class AlbumExpose < Disposable::Composition + # from AlbumTwin # end # - # Composition adds #initialize to the includer. - # - # album = Album.new(cd: CD.find(1), band: Band.new) - # album.id #=> 1 - # album.title = "Ten Foot Pole" - # album.band_id #=> nil - # - # It allows accessing the contained models using the `#[]` reader. - module Composition - def self.included(base) - base.extend(Forwardable) - base.extend(ClassMethods) - end - - - module ClassMethods - def map(options) - @map = {} - - options.each do |mdl, meths| - meths.each do |mtd| # [[:title], [:id, :song_id]] - create_accessors(mdl, mtd) - add_to_map(mdl, mtd) - end - end - end - - private - def create_accessors(model, methods) - def_instance_delegator "@#{model}", *methods # reader - def_instance_delegator "@#{model}", *methods.map { |m| "#{m}=" } # writer - end - - def add_to_map(model, methods) - name, public_name = methods - public_name ||= name - - @map[public_name.to_sym] = {:method => name.to_sym, :model => model.to_sym} - end - end - - + # AlbumExpose.new(artist: OpenStruct.new(name: "AFI")).name #=> "AFI" + class Composition < Expose def initialize(models) - models.each do |name, obj| - instance_variable_set(:"@#{name}", obj) + models.each do |name, model| + instance_variable_set(:"@#{name}", model) end - @_models = models.values + @_models = models end # Allows accessing the contained models. def [](name) - instance_variable_get(:"@#{name}") + instance_variable_get("@#{name}") end - # Allows multiplexing method calls to all composed models. def each(&block) - _models.each(&block) + # TODO: test me. + @_models.values.each(&block) end private - attr_reader :_models + def self.accessors!(public_name, private_name, definition) + model = definition[:on] + define_method("#{public_name}") { self[model].send("#{private_name}") } + define_method("#{public_name}=") { |*args| self[model].send("#{private_name}=", *args) } + end end end \ No newline at end of file