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