Class: Disposable::Twin
- Inherits:
-
Object
- Object
- Disposable::Twin
- Extended by:
- Uber::InheritableAttr
- Includes:
- Initialize, Option
- Defined in:
- lib/disposable/twin.rb,
lib/disposable/twin/new.rb,
lib/disposable/twin/save.rb,
lib/disposable/twin/save_.rb,
lib/disposable/twin/struct.rb,
lib/disposable/twin/builder.rb,
lib/disposable/twin/composition.rb,
lib/disposable/twin/representer.rb
Defined Under Namespace
Modules: Builder, Finders, Initialize, Option, Struct Classes: Composition, Decorator, Definition
Class Method Summary collapse
- .collection(name, options = {}, &block) ⇒ Object
-
.new_representer ⇒ Object
transform incoming model into twin API hash.
-
.pre_save_representer ⇒ Object
call save on all nested twins.
- .property(name, options = {}, &block) ⇒ Object
-
.save_representer ⇒ Object
hash for #update_attributes (model API): “Future World”, album: <Album>.
-
.write_representer ⇒ Object
read/write to twin using twin’s API (e.g. #record= not #album=).
Instance Method Summary collapse
-
#save(processed_map = ObjectMap.new) ⇒ Object
it’s important to stress that #save is the only entry point where we hit the database after initialize.
Methods included from Option
Methods included from Initialize
Class Method Details
.collection(name, options = {}, &block) ⇒ Object
34 35 36 |
# File 'lib/disposable/twin.rb', line 34 def self.collection(name, ={}, &block) property(name, .merge(:collection => true), &block) end |
.new_representer ⇒ Object
transform incoming model into twin API hash.
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# File 'lib/disposable/twin/new.rb', line 4 def self.new_representer representer = Class.new(representer_class) # inherit configuration # wrap incoming nested model in its Twin. representer.representable_attrs. find_all { |attr| attr[:twin] }. each { |attr| attr.merge!( :prepare => lambda { |object, args| if twin = args.[:object_map][object] twin else args.binding[:twin].evaluate(nil).new(object, args.[:object_map]) end }) } # song_title => model.title representer.representable_attrs.each do |attr| attr.merge!( :getter => lambda { |args| args.represented.send("#{args.binding[:private_name]}") }, # DISCUSS: can't we do that with representable's mechanics? ) end representer end |
.pre_save_representer ⇒ Object
call save on all nested twins.
4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# File 'lib/disposable/twin/save.rb', line 4 def self.pre_save_representer representer = Class.new(write_representer) representer.representable_attrs. each { |attr| attr.merge!( :representable => true, :serialize => lambda do |twin, args| processed = args.[:processed_map] twin.save(processed) unless processed[twin] # don't call save if it is already scheduled. end )} representer end |
.property(name, options = {}, &block) ⇒ Object
20 21 22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/disposable/twin.rb', line 20 def self.property(name, ={}, &block) deprecate_as!() # TODO: remove me in 0.1.0 [:private_name] = .delete(:from) || name [:pass_options] = true representer_class.property(name, , &block).tap do |definition| mod = Module.new do define_method(name) { read_property(name, [:private_name]) } define_method("#{name}=") { |value| write_property(name, [:private_name], value) } # TODO: this is more like prototyping. end include mod end end |
.save_representer ⇒ Object
hash for #update_attributes (model API): “Future World”, album: <Album>
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
# File 'lib/disposable/twin/save_.rb', line 4 def self.save_representer # TODO: do that only at compile-time! save = Class.new(write_representer) # inherit configuration save.representable_attrs. find_all { |attr| attr[:twin] }. each { |attr| attr.merge!( :representable => true, :serialize => lambda { |obj, args| obj.send(:model) }) } save.representable_attrs.each do |attr| attr.merge!(:as => attr[:private_name]) end save end |
.write_representer ⇒ Object
read/write to twin using twin’s API (e.g. #record= not #album=).
51 52 53 |
# File 'lib/disposable/twin.rb', line 51 def self.write_representer representer = Class.new(representer_class) # inherit configuration end |
Instance Method Details
#save(processed_map = ObjectMap.new) ⇒ Object
it’s important to stress that #save is the only entry point where we hit the database after initialize.
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/disposable/twin/save.rb', line 21 def save(processed_map=ObjectMap.new) # use that in Reform::AR. processed_map[self] = true pre_save = self.class.pre_save_representer.new(self) pre_save.to_hash(:include => pre_save.twin_names, :processed_map => processed_map) # #save on nested Twins. # what we do right now # call save on all nested twins - how does that work with dependencies (eg Album needs Song id)? # extract all ORM attributes # write to model sync_attrs = self.class.save_representer.new(self).to_hash # puts "sync> #{sync_attrs.inspect}" # this is ORM-specific: model.update_attributes(sync_attrs) # this also does `album: #<Album>` # FIXME: sync again, here, or just id? self.id = model.id end |