disposable 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/README.md +9 -0
- data/STUFF +1 -8
- data/database.sqlite3 +0 -0
- data/disposable.gemspec +1 -1
- data/gemfiles/Gemfile.rails-2.3.lock +13 -2
- data/gemfiles/Gemfile.rails-3.0.lock +13 -2
- data/lib/disposable/composition.rb +30 -9
- data/lib/disposable/facade/active_record.rb +0 -3
- data/lib/disposable/twin.rb +84 -49
- data/lib/disposable/version.rb +1 -1
- data/test/composition_test.rb +96 -0
- data/test/twin/active_record_test.rb +61 -1
- data/test/twin/composition_test.rb +27 -40
- data/test/twin/twin_test.rb +57 -2
- metadata +26 -23
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 3028d579eaa9e41a6d3591c069809c98940bd7a1
         | 
| 4 | 
            +
              data.tar.gz: 12371d78cdf1c2bfe046021f45ffb0a1dbd4ccff
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 2af96f209c219622ac48b55d86798cd392fd83cb73e14463319d965c20a01824e4354ff5f09e9b71bddc21caeb64e369cb265478c77572226c1245297a7f25bc
         | 
| 7 | 
            +
              data.tar.gz: e58b5545c50a104ca16ae784cb48a2280dc60a407f35345dcccf78e867756380993826be1e6d4ce5f442475f0fd1311fddc4f2079f467cf5d1b774ce05b44c07
         | 
    
        data/Gemfile
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | @@ -1,6 +1,9 @@ | |
| 1 1 | 
             
            # Disposable
         | 
| 2 2 |  | 
| 3 3 |  | 
| 4 | 
            +
            why?
         | 
| 5 | 
            +
            because i want this to fuckin work: Wallpaper.find(51).update_attributes(enabled:false)
         | 
| 6 | 
            +
             | 
| 4 7 |  | 
| 5 8 | 
             
            ## Twin
         | 
| 6 9 |  | 
| @@ -82,6 +85,12 @@ song.save # write to DB. | |
| 82 85 |  | 
| 83 86 |  | 
| 84 87 |  | 
| 88 | 
            +
            ## Composition
         | 
| 89 | 
            +
             | 
| 90 | 
            +
            hiding composed datastructures
         | 
| 91 | 
            +
            mapping methods, with optional as:
         | 
| 92 | 
            +
             | 
| 93 | 
            +
             | 
| 85 94 | 
             
            ## To be documented properly
         | 
| 86 95 |  | 
| 87 96 | 
             
            Facade existing (model) class
         | 
    
        data/STUFF
    CHANGED
    
    | @@ -1,11 +1,4 @@ | |
| 1 1 | 
             
            USE CASE:
         | 
| 2 2 |  | 
| 3 3 | 
             
            <% client.invoices.outstanding.each do |invoice| %>
         | 
| 4 | 
            -
                        <%= link_to invoice.invoice_number, {:controller => "party", :action => "invoice_show", :id => invoice.id, :entity_instance_id => client.party, :entity_type_id => EntityType::PARTY}, :onclick => "event.cancelBubble=true;" %> <%= number_to_currency(invoice.balance_out)
         | 
| 5 | 
            -
             | 
| 6 | 
            -
             | 
| 7 | 
            -
            Invoice::Option::Rate <-- uses option everywhere
         | 
| 8 | 
            -
              make that declaratively hook-able:
         | 
| 9 | 
            -
                belongs_to Invoice::Option
         | 
| 10 | 
            -
             | 
| 11 | 
            -
                Invoice::Option#rate => Rate.new(self)
         | 
| 4 | 
            +
                        <%= link_to invoice.invoice_number, {:controller => "party", :action => "invoice_show", :id => invoice.id, :entity_instance_id => client.party, :entity_type_id => EntityType::PARTY}, :onclick => "event.cancelBubble=true;" %> <%= number_to_currency(invoice.balance_out)
         | 
    
        data/database.sqlite3
    CHANGED
    
    | Binary file | 
    
        data/disposable.gemspec
    CHANGED
    
    | @@ -19,7 +19,7 @@ Gem::Specification.new do |spec| | |
| 19 19 | 
             
              spec.require_paths = ["lib"]
         | 
| 20 20 |  | 
| 21 21 | 
             
              spec.add_dependency "uber"
         | 
| 22 | 
            -
              spec.add_dependency "representable"
         | 
| 22 | 
            +
              spec.add_dependency "representable", "~> 1.8.1"
         | 
| 23 23 |  | 
| 24 24 | 
             
              spec.add_development_dependency "bundler", "~> 1.3"
         | 
| 25 25 | 
             
              spec.add_development_dependency "rake"
         | 
| @@ -1,7 +1,9 @@ | |
| 1 1 | 
             
            PATH
         | 
| 2 | 
            -
              remote:  | 
| 2 | 
            +
              remote: ../
         | 
| 3 3 | 
             
              specs:
         | 
| 4 | 
            -
                disposable (0.0. | 
| 4 | 
            +
                disposable (0.0.2)
         | 
| 5 | 
            +
                  representable (~> 1.8.1)
         | 
| 6 | 
            +
                  uber
         | 
| 5 7 |  | 
| 6 8 | 
             
            GEM
         | 
| 7 9 | 
             
              remote: http://rubygems.org/
         | 
| @@ -16,7 +18,11 @@ GEM | |
| 16 18 | 
             
                activeresource (2.3.18)
         | 
| 17 19 | 
             
                  activesupport (= 2.3.18)
         | 
| 18 20 | 
             
                activesupport (2.3.18)
         | 
| 21 | 
            +
                mini_portile (0.5.3)
         | 
| 19 22 | 
             
                minitest (5.0.8)
         | 
| 23 | 
            +
                multi_json (1.9.3)
         | 
| 24 | 
            +
                nokogiri (1.6.1)
         | 
| 25 | 
            +
                  mini_portile (~> 0.5.0)
         | 
| 20 26 | 
             
                rack (1.1.6)
         | 
| 21 27 | 
             
                rails (2.3.18)
         | 
| 22 28 | 
             
                  actionmailer (= 2.3.18)
         | 
| @@ -26,7 +32,12 @@ GEM | |
| 26 32 | 
             
                  activesupport (= 2.3.18)
         | 
| 27 33 | 
             
                  rake (>= 0.8.3)
         | 
| 28 34 | 
             
                rake (10.1.0)
         | 
| 35 | 
            +
                representable (1.8.1)
         | 
| 36 | 
            +
                  multi_json
         | 
| 37 | 
            +
                  nokogiri
         | 
| 38 | 
            +
                  uber
         | 
| 29 39 | 
             
                sqlite3 (1.3.8)
         | 
| 40 | 
            +
                uber (0.0.4)
         | 
| 30 41 |  | 
| 31 42 | 
             
            PLATFORMS
         | 
| 32 43 | 
             
              ruby
         | 
| @@ -1,7 +1,9 @@ | |
| 1 1 | 
             
            PATH
         | 
| 2 | 
            -
              remote:  | 
| 2 | 
            +
              remote: ../
         | 
| 3 3 | 
             
              specs:
         | 
| 4 | 
            -
                disposable (0.0. | 
| 4 | 
            +
                disposable (0.0.2)
         | 
| 5 | 
            +
                  representable (~> 1.8.1)
         | 
| 6 | 
            +
                  uber
         | 
| 5 7 |  | 
| 6 8 | 
             
            GEM
         | 
| 7 9 | 
             
              remote: http://rubygems.org/
         | 
| @@ -33,7 +35,11 @@ GEM | |
| 33 35 | 
             
                  abstract (>= 1.0.0)
         | 
| 34 36 | 
             
                i18n (0.5.0)
         | 
| 35 37 | 
             
                json (1.8.0)
         | 
| 38 | 
            +
                mini_portile (0.5.3)
         | 
| 36 39 | 
             
                minitest (5.0.8)
         | 
| 40 | 
            +
                multi_json (1.9.3)
         | 
| 41 | 
            +
                nokogiri (1.6.1)
         | 
| 42 | 
            +
                  mini_portile (~> 0.5.0)
         | 
| 37 43 | 
             
                rack (1.2.8)
         | 
| 38 44 | 
             
                rack-mount (0.6.14)
         | 
| 39 45 | 
             
                  rack (>= 1.0.0)
         | 
| @@ -48,9 +54,14 @@ GEM | |
| 48 54 | 
             
                rake (10.1.0)
         | 
| 49 55 | 
             
                rdoc (3.12.2)
         | 
| 50 56 | 
             
                  json (~> 1.4)
         | 
| 57 | 
            +
                representable (1.8.1)
         | 
| 58 | 
            +
                  multi_json
         | 
| 59 | 
            +
                  nokogiri
         | 
| 60 | 
            +
                  uber
         | 
| 51 61 | 
             
                sqlite3 (1.3.8)
         | 
| 52 62 | 
             
                thor (0.14.6)
         | 
| 53 63 | 
             
                tzinfo (0.3.38)
         | 
| 64 | 
            +
                uber (0.0.4)
         | 
| 54 65 |  | 
| 55 66 | 
             
            PLATFORMS
         | 
| 56 67 | 
             
              ruby
         | 
| @@ -1,40 +1,55 @@ | |
| 1 | 
            +
            require 'forwardable'
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            module Disposable
         | 
| 2 4 | 
             
              # Composition delegates accessors to models as per configuration.
         | 
| 5 | 
            +
              # Composition doesn't know anything but methods (readers and writers) to expose and the mappings to
         | 
| 6 | 
            +
              # the internal models. Optionally, it knows about renamings such as mapping `#song_id` to `song.id`.
         | 
| 3 7 | 
             
              #
         | 
| 4 8 | 
             
              #   class Album
         | 
| 5 9 | 
             
              #     include Disposable::Composition
         | 
| 6 | 
            -
             | 
| 7 | 
            -
              #     map( {cd: [:id, :name], band: [:title]} )
         | 
| 10 | 
            +
              #
         | 
| 11 | 
            +
              #     map( {cd: [[:id], [:name]], band: [[:id, :band_id], [:title]]} )
         | 
| 8 12 | 
             
              #   end
         | 
| 9 | 
            -
             | 
| 13 | 
            +
              #
         | 
| 10 14 | 
             
              #   album = Album.new(cd: CD.find(1), band: Band.new)
         | 
| 11 15 | 
             
              #   album.id #=> 1
         | 
| 12 16 | 
             
              #   album.title = "Ten Foot Pole"
         | 
| 13 17 | 
             
              module Composition
         | 
| 14 18 | 
             
                def self.included(base)
         | 
| 19 | 
            +
                  base.extend(Forwardable)
         | 
| 15 20 | 
             
                  base.extend(ClassMethods)
         | 
| 16 21 | 
             
                end
         | 
| 17 22 |  | 
| 23 | 
            +
             | 
| 18 24 | 
             
                module ClassMethods
         | 
| 19 25 | 
             
                  def map(options)
         | 
| 20 | 
            -
             | 
| 26 | 
            +
                     @map = {}
         | 
| 21 27 |  | 
| 22 28 | 
             
                    options.each do |mdl, meths|
         | 
| 23 | 
            -
                      create_accessors(mdl, meths)
         | 
| 24 29 | 
             
                      attr_reader mdl
         | 
| 25 30 |  | 
| 26 | 
            -
                      meths.each  | 
| 31 | 
            +
                      meths.each do |mtd| # [[:title], [:id, :song_id]]
         | 
| 32 | 
            +
                        create_accessors(mdl, mtd)
         | 
| 33 | 
            +
                        add_to_map(mdl, mtd)
         | 
| 34 | 
            +
                      end
         | 
| 27 35 | 
             
                    end
         | 
| 28 36 | 
             
                  end
         | 
| 29 37 |  | 
| 38 | 
            +
                private
         | 
| 30 39 | 
             
                  def create_accessors(model, methods)
         | 
| 31 | 
            -
                     | 
| 32 | 
            -
                     | 
| 40 | 
            +
                    def_instance_delegator model, *methods # reader
         | 
| 41 | 
            +
                    def_instance_delegator model, *methods.map { |m| "#{m}=" } # writer
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                  def add_to_map(model, methods)
         | 
| 45 | 
            +
                    name, public_name = methods
         | 
| 46 | 
            +
                    public_name     ||= name
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                    @map[public_name.to_sym] = {:method => name.to_sym, :model => model.to_sym}
         | 
| 33 49 | 
             
                  end
         | 
| 34 50 | 
             
                end
         | 
| 35 51 |  | 
| 36 52 |  | 
| 37 | 
            -
              private
         | 
| 38 53 | 
             
                def initialize(models)
         | 
| 39 54 | 
             
                  models.each do |name, obj|
         | 
| 40 55 | 
             
                    instance_variable_set(:"@#{name}", obj)
         | 
| @@ -43,6 +58,12 @@ module Disposable | |
| 43 58 | 
             
                  @_models = models.values
         | 
| 44 59 | 
             
                end
         | 
| 45 60 |  | 
| 61 | 
            +
                # Allows multiplexing method calls to all composed models.
         | 
| 62 | 
            +
                def each(&block)
         | 
| 63 | 
            +
                  _models.each(&block)
         | 
| 64 | 
            +
                end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
              private
         | 
| 46 67 | 
             
                attr_reader:_models
         | 
| 47 68 | 
             
              end
         | 
| 48 69 | 
             
            end
         | 
| @@ -2,9 +2,6 @@ class Disposable::Facade | |
| 2 2 | 
             
              module ActiveRecord
         | 
| 3 3 | 
             
                def is_a?(klass)
         | 
| 4 4 | 
             
                  # DISCUSS: should we use facade_options here for the class?
         | 
| 5 | 
            -
                  #return self.class.facade_options.first == klass if self.class.facade_options.first
         | 
| 6 | 
            -
                  # DISCUSS: make ::facades obligatory?
         | 
| 7 | 
            -
             | 
| 8 5 | 
             
                  klass == __getobj__.class or super
         | 
| 9 6 | 
             
                end
         | 
| 10 7 | 
             
              end
         | 
    
        data/lib/disposable/twin.rb
    CHANGED
    
    | @@ -13,36 +13,14 @@ module Disposable | |
| 13 13 | 
             
                    Class.new(self) # By subclassing, representable_attrs.clone is called.
         | 
| 14 14 | 
             
                  end
         | 
| 15 15 |  | 
| 16 | 
            -
                  def  | 
| 17 | 
            -
                     | 
| 18 | 
            -
                  end
         | 
| 19 | 
            -
             | 
| 20 | 
            -
                  def self.twin_names
         | 
| 21 | 
            -
                    representable_attrs.twin_names
         | 
| 22 | 
            -
                  end
         | 
| 23 | 
            -
             | 
| 24 | 
            -
                  def twins(&block)
         | 
| 25 | 
            -
                    clone_config!.
         | 
| 26 | 
            -
                        find_all { |attr| attr[:form] }.
         | 
| 27 | 
            -
                        each(&block)
         | 
| 28 | 
            -
                    end
         | 
| 29 | 
            -
             | 
| 30 | 
            -
                  module ConfigExtensions
         | 
| 31 | 
            -
                    def twin_names
         | 
| 16 | 
            +
                  def twin_names
         | 
| 17 | 
            +
                    representable_attrs.
         | 
| 32 18 | 
             
                      find_all { |attr| attr[:twin] }.
         | 
| 33 | 
            -
                      collect { |attr| attr.name }
         | 
| 34 | 
            -
                    end
         | 
| 35 | 
            -
                  end
         | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 38 | 
            -
                  class Save < self
         | 
| 39 | 
            -
             | 
| 19 | 
            +
                      collect { |attr| attr.name.to_sym }
         | 
| 40 20 | 
             
                  end
         | 
| 41 21 | 
             
                end
         | 
| 42 22 |  | 
| 43 23 |  | 
| 44 | 
            -
             | 
| 45 | 
            -
             | 
| 46 24 | 
             
                extend Uber::InheritableAttr
         | 
| 47 25 | 
             
                inheritable_attr :representer_class
         | 
| 48 26 | 
             
                self.representer_class = Class.new(Decorator)
         | 
| @@ -53,10 +31,13 @@ module Disposable | |
| 53 31 | 
             
                  self._model = name
         | 
| 54 32 | 
             
                end
         | 
| 55 33 |  | 
| 56 | 
            -
                def self.property(name,  | 
| 57 | 
            -
                   | 
| 34 | 
            +
                def self.property(name, options={}, &block)
         | 
| 35 | 
            +
                  options[:public_name]  = options.delete(:as) || name
         | 
| 36 | 
            +
                  options[:pass_options] = true
         | 
| 58 37 |  | 
| 59 | 
            -
                  representer_class.property(name,  | 
| 38 | 
            +
                  representer_class.property(name, options, &block).tap do |definition|
         | 
| 39 | 
            +
                    attr_accessor definition[:public_name]
         | 
| 40 | 
            +
                  end
         | 
| 60 41 | 
             
                end
         | 
| 61 42 |  | 
| 62 43 | 
             
                def self.from(model) # TODO: private.
         | 
| @@ -72,49 +53,68 @@ module Disposable | |
| 72 53 | 
             
                  new(_model.find(id))
         | 
| 73 54 | 
             
                end
         | 
| 74 55 |  | 
| 56 | 
            +
                # hash for #update_attributes (model API): {title: "Future World", album: <Album>}
         | 
| 75 57 | 
             
                def self.save_representer
         | 
| 76 58 | 
             
                  # TODO: do that only at compile-time!
         | 
| 77 | 
            -
                  save = Class.new( | 
| 59 | 
            +
                  save = Class.new(write_representer) # inherit configuration
         | 
| 78 60 | 
             
                  save.representable_attrs.
         | 
| 79 61 | 
             
                    find_all { |attr| attr[:twin] }.
         | 
| 80 62 | 
             
                    each { |attr| attr.merge!(
         | 
| 81 | 
            -
                      :representable => true | 
| 63 | 
            +
                      :representable => true,
         | 
| 64 | 
            +
                      :serialize     => lambda { |obj, args| obj.send(:model) }) }
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                    save.representable_attrs.each do |attr|
         | 
| 67 | 
            +
                      attr.merge!(:as => attr.name)
         | 
| 68 | 
            +
                    end
         | 
| 69 | 
            +
             | 
| 82 70 | 
             
                  save
         | 
| 83 71 | 
             
                end
         | 
| 84 72 |  | 
| 73 | 
            +
                # transform incoming model into twin API hash.
         | 
| 85 74 | 
             
                def self.new_representer
         | 
| 86 75 | 
             
                  representer = Class.new(representer_class) # inherit configuration
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                  # wrap incoming nested model in it's Twin.
         | 
| 87 78 | 
             
                  representer.representable_attrs.
         | 
| 88 79 | 
             
                    find_all { |attr| attr[:twin] }.
         | 
| 89 80 | 
             
                    each { |attr| attr.merge!(
         | 
| 90 | 
            -
                      :pass_options => true,
         | 
| 91 81 | 
             
                      :prepare      => lambda { |object, args| args.binding[:twin].new(object) }) }
         | 
| 92 | 
            -
                  representer
         | 
| 93 | 
            -
                end
         | 
| 94 82 |  | 
| 83 | 
            +
                  # song_title => model.title
         | 
| 84 | 
            +
                  representer.representable_attrs.each do |attr|
         | 
| 85 | 
            +
                    attr.merge!(:as => attr[:public_name])
         | 
| 86 | 
            +
                  end
         | 
| 95 87 |  | 
| 96 | 
            -
             | 
| 97 | 
            -
                  model
         | 
| 88 | 
            +
                  representer
         | 
| 98 89 | 
             
                end
         | 
| 99 90 |  | 
| 100 | 
            -
                #  | 
| 101 | 
            -
                def  | 
| 102 | 
            -
                   | 
| 103 | 
            -
             | 
| 104 | 
            -
             | 
| 105 | 
            -
             | 
| 106 | 
            -
             | 
| 91 | 
            +
                # read/write to twin using twin's API (e.g. #record= not #album=).
         | 
| 92 | 
            +
                def self.write_representer
         | 
| 93 | 
            +
                  representer = Class.new(representer_class) # inherit configuration
         | 
| 94 | 
            +
                  representer.representable_attrs.
         | 
| 95 | 
            +
                    each { |attr| attr.merge!(
         | 
| 96 | 
            +
                      # use the alias name (as:) when writing attributes in new.
         | 
| 97 | 
            +
                      # DISCUSS: attr.name = public_name would be simpler.
         | 
| 98 | 
            +
                      :as => attr[:public_name],
         | 
| 99 | 
            +
                      :getter      => lambda { |args|        send("#{args.binding[:public_name]}") },
         | 
| 100 | 
            +
                      :setter      => lambda { |value, args| send("#{args.binding[:public_name]}=", value) }
         | 
| 101 | 
            +
                    )}
         | 
| 107 102 |  | 
| 103 | 
            +
                  representer
         | 
| 104 | 
            +
                end
         | 
| 108 105 |  | 
| 109 | 
            -
             | 
| 110 | 
            -
             | 
| 111 | 
            -
                   | 
| 106 | 
            +
                # call save on all nested twins.
         | 
| 107 | 
            +
                def self.pre_save_representer
         | 
| 108 | 
            +
                  representer = Class.new(write_representer)
         | 
| 109 | 
            +
                  representer.representable_attrs.
         | 
| 110 | 
            +
                    each { |attr| attr.merge!(
         | 
| 111 | 
            +
                      :representable => true,
         | 
| 112 | 
            +
                      :serialize => lambda { |model, args| model.save }
         | 
| 113 | 
            +
                    )}
         | 
| 112 114 |  | 
| 113 | 
            -
                   | 
| 114 | 
            -
                  self.id = model.id
         | 
| 115 | 
            +
                  representer
         | 
| 115 116 | 
             
                end
         | 
| 116 117 |  | 
| 117 | 
            -
                # below is the code for a representable-style twin:
         | 
| 118 118 |  | 
| 119 119 | 
             
                # TODO: improve speed when setting up a twin.
         | 
| 120 120 | 
             
                def initialize(model, options={})
         | 
| @@ -125,11 +125,46 @@ module Disposable | |
| 125 125 | 
             
                    merge(options))
         | 
| 126 126 | 
             
                end
         | 
| 127 127 |  | 
| 128 | 
            +
                # it's important to stress that #save is the only entry point where we hit the database after initialize.
         | 
| 129 | 
            +
                def save # use that in Reform::AR.
         | 
| 130 | 
            +
                  pre_save = self.class.pre_save_representer.new(self)
         | 
| 131 | 
            +
                  pre_save.to_hash(:include => pre_save.twin_names) # #save on nested Twins.
         | 
| 132 | 
            +
             | 
| 133 | 
            +
             | 
| 134 | 
            +
             | 
| 135 | 
            +
                  # what we do right now
         | 
| 136 | 
            +
                  # call save on all nested twins - how does that work with dependencies (eg Album needs Song id)?
         | 
| 137 | 
            +
                  # extract all ORM attributes
         | 
| 138 | 
            +
                  # write to model
         | 
| 139 | 
            +
             | 
| 140 | 
            +
                  sync_attrs    = self.class.save_representer.new(self).to_hash
         | 
| 141 | 
            +
                  # puts "sync> #{sync_attrs.inspect}"
         | 
| 142 | 
            +
                  # this is ORM-specific:
         | 
| 143 | 
            +
                  model.update_attributes(sync_attrs) # this also does `album: #<Album>`
         | 
| 144 | 
            +
             | 
| 145 | 
            +
                  # FIXME: sync again, here, or just id?
         | 
| 146 | 
            +
                  self.id = model.id
         | 
| 147 | 
            +
                end
         | 
| 148 | 
            +
             | 
| 128 149 | 
             
              private
         | 
| 129 150 | 
             
                def from_hash(options={})
         | 
| 130 | 
            -
                  self.class. | 
| 151 | 
            +
                  self.class.write_representer.new(self).from_hash(options)
         | 
| 131 152 | 
             
                end
         | 
| 132 153 |  | 
| 133 154 | 
             
                attr_reader :model # TODO: test
         | 
| 155 | 
            +
             | 
| 156 | 
            +
             | 
| 157 | 
            +
                # class Composition < self
         | 
| 158 | 
            +
                #   def initialize(hash)
         | 
| 159 | 
            +
                #     hash = hash.first
         | 
| 160 | 
            +
                #     composition = Class.new do
         | 
| 161 | 
            +
                #       include Disposable::Composition
         | 
| 162 | 
            +
                #       map( {:song => [:song_title], :requester => [:name]})
         | 
| 163 | 
            +
                #       self
         | 
| 164 | 
            +
                #     end.new(hash)
         | 
| 165 | 
            +
             | 
| 166 | 
            +
                #     super(composition)
         | 
| 167 | 
            +
                #   end
         | 
| 168 | 
            +
                # end
         | 
| 134 169 | 
             
              end
         | 
| 135 170 | 
             
            end
         | 
    
        data/lib/disposable/version.rb
    CHANGED
    
    
| @@ -0,0 +1,96 @@ | |
| 1 | 
            +
            require 'test_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            class CompositionTest < MiniTest::Spec
         | 
| 4 | 
            +
              module Model
         | 
| 5 | 
            +
                Band  = Struct.new(:id, :title,)
         | 
| 6 | 
            +
                Album = Struct.new(:id, :name)
         | 
| 7 | 
            +
              end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              module Twin
         | 
| 10 | 
            +
                class Album #< Disposable::Twin
         | 
| 11 | 
            +
                  include Disposable::Composition
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  map( {:album => [[:id], [:name]],
         | 
| 14 | 
            +
                        :band  => [[:id, :band_id], [:title]]
         | 
| 15 | 
            +
                      } )
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
              let (:band) { Model::Band.new(1, "Frenzal Rhomb") }
         | 
| 20 | 
            +
              let (:album) { Model::Album.new(2, "Dick Sandwhich") }
         | 
| 21 | 
            +
              subject { Twin::Album.new(:album => album, :band => band) }
         | 
| 22 | 
            +
             | 
| 23 | 
            +
              describe "readers" do
         | 
| 24 | 
            +
                it { subject.id.must_equal 2 }
         | 
| 25 | 
            +
                it { subject.band_id.must_equal 1 }
         | 
| 26 | 
            +
                it { subject.name.must_equal "Dick Sandwhich" }
         | 
| 27 | 
            +
                it { subject.title.must_equal "Frenzal Rhomb" }
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
             | 
| 31 | 
            +
              describe "writers" do
         | 
| 32 | 
            +
                before do
         | 
| 33 | 
            +
                  subject.id = 3
         | 
| 34 | 
            +
                  subject.band_id = 4
         | 
| 35 | 
            +
                  subject.name = "Eclipse"
         | 
| 36 | 
            +
                  subject.title = "Yngwie J. Malmsteen"
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                it { subject.id.must_equal 3 }
         | 
| 40 | 
            +
                it { album.id.must_equal   3 }
         | 
| 41 | 
            +
                it { subject.band_id.must_equal 4 }
         | 
| 42 | 
            +
                it { band.id.must_equal 4 }
         | 
| 43 | 
            +
                it { subject.name.must_equal "Eclipse" }
         | 
| 44 | 
            +
                it { subject.title.must_equal "Yngwie J. Malmsteen" }
         | 
| 45 | 
            +
                it { album.name.must_equal "Eclipse" }
         | 
| 46 | 
            +
                it { band.title.must_equal "Yngwie J. Malmsteen" }
         | 
| 47 | 
            +
              end
         | 
| 48 | 
            +
              # it { subject.save }
         | 
| 49 | 
            +
             | 
| 50 | 
            +
              it "raises when non-mapped property" do
         | 
| 51 | 
            +
                assert_raises NoMethodError do
         | 
| 52 | 
            +
                  subject.raise_an_exception
         | 
| 53 | 
            +
                end
         | 
| 54 | 
            +
              end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
             | 
| 57 | 
            +
              describe "readers to models" do
         | 
| 58 | 
            +
                it { subject.album.object_id.must_equal album.object_id }
         | 
| 59 | 
            +
                it { subject.band.object_id.must_equal  band.object_id }
         | 
| 60 | 
            +
              end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
             | 
| 63 | 
            +
              describe "#each" do
         | 
| 64 | 
            +
                it "what" do
         | 
| 65 | 
            +
                  results = []
         | 
| 66 | 
            +
                  subject.each { |mdl| results << mdl.object_id }
         | 
| 67 | 
            +
                  results.must_equal([album.object_id, band.object_id])
         | 
| 68 | 
            +
                end
         | 
| 69 | 
            +
              end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
             | 
| 72 | 
            +
              describe "#_models" do
         | 
| 73 | 
            +
                it { subject.send(:_models).must_equal([album, band]) }
         | 
| 74 | 
            +
                it { Twin::Album.new(:album => album).send(:_models).must_equal([album]) }
         | 
| 75 | 
            +
              end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
             | 
| 78 | 
            +
              describe "@map" do
         | 
| 79 | 
            +
                let (:composition) {
         | 
| 80 | 
            +
                  Class.new do
         | 
| 81 | 
            +
                    include Disposable::Composition
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                    map( {:album => [["id"], [:name]],
         | 
| 84 | 
            +
                          "band" => [[:id, "band_id"], [:title]]
         | 
| 85 | 
            +
                      } )
         | 
| 86 | 
            +
                  end
         | 
| 87 | 
            +
                }
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                # yepp, a private test WITH interface violation, as this is still a semi-public concept.
         | 
| 90 | 
            +
                it { composition.instance_variable_get(:@map).must_equal({
         | 
| 91 | 
            +
                  :id      => {:method=>:id, :model=>:album},
         | 
| 92 | 
            +
                  :name    => {:method=>:name, :model=>:album},
         | 
| 93 | 
            +
                  :band_id => {:method=>:id, :model=>:band},
         | 
| 94 | 
            +
                  :title   => {:method=>:title, :model=>:band}}) }
         | 
| 95 | 
            +
              end
         | 
| 96 | 
            +
            end
         | 
| @@ -85,6 +85,7 @@ class TwinActiveRecordTest < MiniTest::Spec | |
| 85 85 | 
             
                  must_equal({"id" => subject.id, "title" => "Broken"}) }
         | 
| 86 86 |  | 
| 87 87 | 
             
                it { subject.album.must_equal album }
         | 
| 88 | 
            +
                it { subject.album.id.wont_equal nil } # FIXME: this only works because song is saved after album.
         | 
| 88 89 | 
             
              end
         | 
| 89 90 |  | 
| 90 91 |  | 
| @@ -101,4 +102,63 @@ class TwinActiveRecordTest < MiniTest::Spec | |
| 101 102 |  | 
| 102 103 | 
             
                it { subject.album.attributes.slice("name").must_equal("name" => "Billy Talent") }
         | 
| 103 104 | 
             
              end
         | 
| 104 | 
            -
            end
         | 
| 105 | 
            +
            end
         | 
| 106 | 
            +
             | 
| 107 | 
            +
             | 
| 108 | 
            +
            class TwinActiveRecordAsTest < MiniTest::Spec
         | 
| 109 | 
            +
              module Twin
         | 
| 110 | 
            +
                class Album < Disposable::Twin
         | 
| 111 | 
            +
                  property :id
         | 
| 112 | 
            +
                  property :name, :as => :album_name
         | 
| 113 | 
            +
             | 
| 114 | 
            +
                  model ::Album
         | 
| 115 | 
            +
                end
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                class Song < Disposable::Twin
         | 
| 118 | 
            +
                  property :id
         | 
| 119 | 
            +
                  property :title, :as => :song_title
         | 
| 120 | 
            +
                  property :album, :twin => Album, :as => :record
         | 
| 121 | 
            +
             | 
| 122 | 
            +
                  model ::Song
         | 
| 123 | 
            +
                end
         | 
| 124 | 
            +
              end
         | 
| 125 | 
            +
             | 
| 126 | 
            +
             | 
| 127 | 
            +
              describe "::from" do
         | 
| 128 | 
            +
                 # (existing models)
         | 
| 129 | 
            +
                let (:song) { ::Song.new(:title => "Broken", :album => album) }
         | 
| 130 | 
            +
                let (:album) { ::Album.new(:name => "The Process Of Belief") }
         | 
| 131 | 
            +
             | 
| 132 | 
            +
                let(:twin) { Twin::Song.from(song) }
         | 
| 133 | 
            +
             | 
| 134 | 
            +
                it { twin.song_title.must_equal "Broken" }
         | 
| 135 | 
            +
                it { twin.record.album_name.must_equal "The Process Of Belief" }
         | 
| 136 | 
            +
              end
         | 
| 137 | 
            +
             | 
| 138 | 
            +
             | 
| 139 | 
            +
              describe "#save" do
         | 
| 140 | 
            +
                # existing models
         | 
| 141 | 
            +
                let (:song) { ::Song.new(:title => "Broken", :album => album) }
         | 
| 142 | 
            +
                let (:album) { ::Album.new(:name => "The Process Of  Belief") }
         | 
| 143 | 
            +
             | 
| 144 | 
            +
                let(:twin) { Twin::Song.from(song) }
         | 
| 145 | 
            +
             | 
| 146 | 
            +
                before do
         | 
| 147 | 
            +
                  twin.song_title = "Emo Boy"
         | 
| 148 | 
            +
                  twin.record.album_name = "Rode Hard And Put Away Wet"
         | 
| 149 | 
            +
             | 
| 150 | 
            +
                  twin.save
         | 
| 151 | 
            +
                end
         | 
| 152 | 
            +
             | 
| 153 | 
            +
                let (:ar_song) { ::Song.find(twin.id) }
         | 
| 154 | 
            +
                let (:ar_album) { ar_song.album }
         | 
| 155 | 
            +
             | 
| 156 | 
            +
                it { ar_song.attributes.slice("id", "title").
         | 
| 157 | 
            +
                  must_equal({"id" => ar_song.id, "title" => "Emo Boy"}) }
         | 
| 158 | 
            +
             | 
| 159 | 
            +
                it { ar_album.must_equal album }
         | 
| 160 | 
            +
                it("xxx") { ar_album.name.must_equal "Rode Hard And Put Away Wet" }
         | 
| 161 | 
            +
                it { ar_album.id.wont_equal nil } # FIXME: this only works because song is saved after album.
         | 
| 162 | 
            +
              end
         | 
| 163 | 
            +
             | 
| 164 | 
            +
            end
         | 
| @@ -1,50 +1,37 @@ | |
| 1 | 
            -
            require 'test_helper'
         | 
| 1 | 
            +
            # require 'test_helper'
         | 
| 2 2 |  | 
| 3 | 
            -
            class  | 
| 4 | 
            -
             | 
| 5 | 
            -
             | 
| 6 | 
            -
                 | 
| 7 | 
            -
              end
         | 
| 3 | 
            +
            # class TwinCompositionTest < MiniTest::Spec
         | 
| 4 | 
            +
            #   class Request < Disposable::Twin::Composition
         | 
| 5 | 
            +
            #     property :title, :on => :song, :as => :song_title
         | 
| 6 | 
            +
            #     property :id,    :on => :song, :as => :song_id
         | 
| 8 7 |  | 
| 9 | 
            -
               | 
| 10 | 
            -
                class Album #< Disposable::Twin
         | 
| 11 | 
            -
                  include Disposable::Composition
         | 
| 12 | 
            -
                  extend Disposable::Composition::ClassMethods # FIXME.
         | 
| 8 | 
            +
            #     property :name,  :on => :requester
         | 
| 13 9 |  | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
                  # property :title,  :on => :band # as: :band_name
         | 
| 10 | 
            +
            #     # map ...
         | 
| 11 | 
            +
            #   end
         | 
| 17 12 |  | 
| 18 | 
            -
             | 
| 13 | 
            +
            #   module Model
         | 
| 14 | 
            +
            #     Song      = Struct.new(:id, :title, :album)
         | 
| 15 | 
            +
            #     Requester = Struct.new(:id, :name)
         | 
| 16 | 
            +
            #   end
         | 
| 19 17 |  | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
              end
         | 
| 18 | 
            +
            #   let (:requester) { Model::Requester.new(1, "Greg Howe") }
         | 
| 19 | 
            +
            #   let (:song) { Model::Song.new(2, "Extraction") }
         | 
| 23 20 |  | 
| 24 | 
            -
             | 
| 25 | 
            -
              let (:album) { Model::Album.new(2, "Dick Sandwhich") }
         | 
| 26 | 
            -
              subject { Twin::Album.new(:album => album, :band => band) }
         | 
| 21 | 
            +
            #   let (:request) { Request.new([:song => song, :requester => requester]) }
         | 
| 27 22 |  | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
              it { subject.title.must_equal "Frenzal Rhomb" }
         | 
| 23 | 
            +
            #   it { request.song_title.must_equal "Extraction" }
         | 
| 24 | 
            +
            #   it { request.name.must_equal "Greg Howe" }
         | 
| 31 25 |  | 
| 32 | 
            -
              # it { subject.save }
         | 
| 33 26 |  | 
| 34 | 
            -
             | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 27 | 
            +
            #   describe "setter" do
         | 
| 28 | 
            +
            #     before do
         | 
| 29 | 
            +
            #       request.song_title = "Tease"
         | 
| 30 | 
            +
            #       request.name = "Wooten"
         | 
| 31 | 
            +
            #     end
         | 
| 39 32 |  | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            -
             | 
| 44 | 
            -
             | 
| 45 | 
            -
             | 
| 46 | 
            -
              describe "#_models" do
         | 
| 47 | 
            -
                it { subject.send(:_models).must_equal([album, band]) }
         | 
| 48 | 
            -
                it { Twin::Album.new(:album => album).send(:_models).must_equal([album]) }
         | 
| 49 | 
            -
              end
         | 
| 50 | 
            -
            end
         | 
| 33 | 
            +
            #     it { request.song_title.must_equal "Tease" }
         | 
| 34 | 
            +
            #     it { song.title.must_equal "Tease" }
         | 
| 35 | 
            +
            #     it { request.name.must_equal "Wooten" }
         | 
| 36 | 
            +
            #   end
         | 
| 37 | 
            +
            # end
         | 
    
        data/test/twin/twin_test.rb
    CHANGED
    
    | @@ -67,9 +67,9 @@ end | |
| 67 67 |  | 
| 68 68 |  | 
| 69 69 | 
             
            class TwinDecoratorTest < MiniTest::Spec
         | 
| 70 | 
            -
              subject { TwinTest::Twin::Song.representer_class }
         | 
| 70 | 
            +
              subject { TwinTest::Twin::Song.representer_class.new(nil) }
         | 
| 71 71 |  | 
| 72 | 
            -
              it { subject.twin_names.must_equal [ | 
| 72 | 
            +
              it { subject.twin_names.must_equal [:album] }
         | 
| 73 73 | 
             
            end
         | 
| 74 74 |  | 
| 75 75 | 
             
            # from is as close to from_hash as possible
         | 
| @@ -77,3 +77,58 @@ end | |
| 77 77 |  | 
| 78 78 |  | 
| 79 79 | 
             
            # should #new create empty associated models?
         | 
| 80 | 
            +
             | 
| 81 | 
            +
             | 
| 82 | 
            +
            class TwinAsTest < MiniTest::Spec
         | 
| 83 | 
            +
              module Model
         | 
| 84 | 
            +
                Song  = Struct.new(:title, :album)
         | 
| 85 | 
            +
                Album = Struct.new(:name)
         | 
| 86 | 
            +
              end
         | 
| 87 | 
            +
             | 
| 88 | 
            +
             | 
| 89 | 
            +
              module Twin
         | 
| 90 | 
            +
                class Album < Disposable::Twin
         | 
| 91 | 
            +
                  property :name, :as => :record_name
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                  model Model::Album
         | 
| 94 | 
            +
                end
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                class Song < Disposable::Twin
         | 
| 97 | 
            +
                  property :title, :as => :name
         | 
| 98 | 
            +
                  property :album, :twin => Album, :as => :record
         | 
| 99 | 
            +
             | 
| 100 | 
            +
                  model Model::Song
         | 
| 101 | 
            +
                end
         | 
| 102 | 
            +
              end
         | 
| 103 | 
            +
             | 
| 104 | 
            +
             | 
| 105 | 
            +
              let (:record) { Twin::Album.new(:record_name => "Veni Vidi Vicous") }
         | 
| 106 | 
            +
              subject { Twin::Song.new(:name => "Outsmarted", :record => record) }
         | 
| 107 | 
            +
             | 
| 108 | 
            +
             | 
| 109 | 
            +
              describe "::new" do # TODO: this creates a new model!
         | 
| 110 | 
            +
                # the Twin exposes the as: API.
         | 
| 111 | 
            +
                it { subject.name.must_equal "Outsmarted" }
         | 
| 112 | 
            +
                it { subject.record.must_equal record }
         | 
| 113 | 
            +
              end
         | 
| 114 | 
            +
             | 
| 115 | 
            +
              # DISCUSS: should we test saving without AR? is that worth the hustle?
         | 
| 116 | 
            +
              # describe "#save" do
         | 
| 117 | 
            +
              #   before { subject.send(:model).instance_eval do
         | 
| 118 | 
            +
              #     def update_attributes(*)
         | 
| 119 | 
            +
             | 
| 120 | 
            +
              #     end
         | 
| 121 | 
            +
              #   end
         | 
| 122 | 
            +
              #   subject.save
         | 
| 123 | 
            +
              # }
         | 
| 124 | 
            +
             | 
| 125 | 
            +
             | 
| 126 | 
            +
             | 
| 127 | 
            +
              #   # before { subject.save }
         | 
| 128 | 
            +
             | 
| 129 | 
            +
              #   it { subject.name }
         | 
| 130 | 
            +
              # end
         | 
| 131 | 
            +
            end
         | 
| 132 | 
            +
             | 
| 133 | 
            +
             | 
| 134 | 
            +
            # TODO: test coercion!
         | 
    
        metadata
    CHANGED
    
    | @@ -1,111 +1,111 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: disposable
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.0. | 
| 4 | 
            +
              version: 0.0.3
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Nick Sutterer
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2014-04- | 
| 11 | 
            +
            date: 2014-04-30 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: uber
         | 
| 15 15 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 16 16 | 
             
                requirements:
         | 
| 17 | 
            -
                - -  | 
| 17 | 
            +
                - - ">="
         | 
| 18 18 | 
             
                  - !ruby/object:Gem::Version
         | 
| 19 19 | 
             
                    version: '0'
         | 
| 20 20 | 
             
              type: :runtime
         | 
| 21 21 | 
             
              prerelease: false
         | 
| 22 22 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 23 23 | 
             
                requirements:
         | 
| 24 | 
            -
                - -  | 
| 24 | 
            +
                - - ">="
         | 
| 25 25 | 
             
                  - !ruby/object:Gem::Version
         | 
| 26 26 | 
             
                    version: '0'
         | 
| 27 27 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 28 28 | 
             
              name: representable
         | 
| 29 29 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 30 30 | 
             
                requirements:
         | 
| 31 | 
            -
                - -  | 
| 31 | 
            +
                - - "~>"
         | 
| 32 32 | 
             
                  - !ruby/object:Gem::Version
         | 
| 33 | 
            -
                    version:  | 
| 33 | 
            +
                    version: 1.8.1
         | 
| 34 34 | 
             
              type: :runtime
         | 
| 35 35 | 
             
              prerelease: false
         | 
| 36 36 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 37 37 | 
             
                requirements:
         | 
| 38 | 
            -
                - -  | 
| 38 | 
            +
                - - "~>"
         | 
| 39 39 | 
             
                  - !ruby/object:Gem::Version
         | 
| 40 | 
            -
                    version:  | 
| 40 | 
            +
                    version: 1.8.1
         | 
| 41 41 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 42 42 | 
             
              name: bundler
         | 
| 43 43 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 44 44 | 
             
                requirements:
         | 
| 45 | 
            -
                - - ~>
         | 
| 45 | 
            +
                - - "~>"
         | 
| 46 46 | 
             
                  - !ruby/object:Gem::Version
         | 
| 47 47 | 
             
                    version: '1.3'
         | 
| 48 48 | 
             
              type: :development
         | 
| 49 49 | 
             
              prerelease: false
         | 
| 50 50 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 51 51 | 
             
                requirements:
         | 
| 52 | 
            -
                - - ~>
         | 
| 52 | 
            +
                - - "~>"
         | 
| 53 53 | 
             
                  - !ruby/object:Gem::Version
         | 
| 54 54 | 
             
                    version: '1.3'
         | 
| 55 55 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 56 56 | 
             
              name: rake
         | 
| 57 57 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 58 58 | 
             
                requirements:
         | 
| 59 | 
            -
                - -  | 
| 59 | 
            +
                - - ">="
         | 
| 60 60 | 
             
                  - !ruby/object:Gem::Version
         | 
| 61 61 | 
             
                    version: '0'
         | 
| 62 62 | 
             
              type: :development
         | 
| 63 63 | 
             
              prerelease: false
         | 
| 64 64 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 65 65 | 
             
                requirements:
         | 
| 66 | 
            -
                - -  | 
| 66 | 
            +
                - - ">="
         | 
| 67 67 | 
             
                  - !ruby/object:Gem::Version
         | 
| 68 68 | 
             
                    version: '0'
         | 
| 69 69 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 70 70 | 
             
              name: minitest
         | 
| 71 71 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 72 72 | 
             
                requirements:
         | 
| 73 | 
            -
                - -  | 
| 73 | 
            +
                - - ">="
         | 
| 74 74 | 
             
                  - !ruby/object:Gem::Version
         | 
| 75 75 | 
             
                    version: '0'
         | 
| 76 76 | 
             
              type: :development
         | 
| 77 77 | 
             
              prerelease: false
         | 
| 78 78 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 79 79 | 
             
                requirements:
         | 
| 80 | 
            -
                - -  | 
| 80 | 
            +
                - - ">="
         | 
| 81 81 | 
             
                  - !ruby/object:Gem::Version
         | 
| 82 82 | 
             
                    version: '0'
         | 
| 83 83 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 84 84 | 
             
              name: activerecord
         | 
| 85 85 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 86 86 | 
             
                requirements:
         | 
| 87 | 
            -
                - -  | 
| 87 | 
            +
                - - ">="
         | 
| 88 88 | 
             
                  - !ruby/object:Gem::Version
         | 
| 89 89 | 
             
                    version: '0'
         | 
| 90 90 | 
             
              type: :development
         | 
| 91 91 | 
             
              prerelease: false
         | 
| 92 92 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 93 93 | 
             
                requirements:
         | 
| 94 | 
            -
                - -  | 
| 94 | 
            +
                - - ">="
         | 
| 95 95 | 
             
                  - !ruby/object:Gem::Version
         | 
| 96 96 | 
             
                    version: '0'
         | 
| 97 97 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 98 98 | 
             
              name: sqlite3
         | 
| 99 99 | 
             
              requirement: !ruby/object:Gem::Requirement
         | 
| 100 100 | 
             
                requirements:
         | 
| 101 | 
            -
                - -  | 
| 101 | 
            +
                - - ">="
         | 
| 102 102 | 
             
                  - !ruby/object:Gem::Version
         | 
| 103 103 | 
             
                    version: '0'
         | 
| 104 104 | 
             
              type: :development
         | 
| 105 105 | 
             
              prerelease: false
         | 
| 106 106 | 
             
              version_requirements: !ruby/object:Gem::Requirement
         | 
| 107 107 | 
             
                requirements:
         | 
| 108 | 
            -
                - -  | 
| 108 | 
            +
                - - ">="
         | 
| 109 109 | 
             
                  - !ruby/object:Gem::Version
         | 
| 110 110 | 
             
                    version: '0'
         | 
| 111 111 | 
             
            description: Domain-Oriented Refactoring Framework.
         | 
| @@ -115,8 +115,8 @@ executables: [] | |
| 115 115 | 
             
            extensions: []
         | 
| 116 116 | 
             
            extra_rdoc_files: []
         | 
| 117 117 | 
             
            files:
         | 
| 118 | 
            -
            - .gitignore
         | 
| 119 | 
            -
            - .travis.yml
         | 
| 118 | 
            +
            - ".gitignore"
         | 
| 119 | 
            +
            - ".travis.yml"
         | 
| 120 120 | 
             
            - Gemfile
         | 
| 121 121 | 
             
            - LICENSE.txt
         | 
| 122 122 | 
             
            - README.md
         | 
| @@ -135,6 +135,7 @@ files: | |
| 135 135 | 
             
            - lib/disposable/twin.rb
         | 
| 136 136 | 
             
            - lib/disposable/version.rb
         | 
| 137 137 | 
             
            - test/active_record_test.rb
         | 
| 138 | 
            +
            - test/composition_test.rb
         | 
| 138 139 | 
             
            - test/facade_test.rb
         | 
| 139 140 | 
             
            - test/test_helper.rb
         | 
| 140 141 | 
             
            - test/twin/active_record_test.rb
         | 
| @@ -150,24 +151,26 @@ require_paths: | |
| 150 151 | 
             
            - lib
         | 
| 151 152 | 
             
            required_ruby_version: !ruby/object:Gem::Requirement
         | 
| 152 153 | 
             
              requirements:
         | 
| 153 | 
            -
              - -  | 
| 154 | 
            +
              - - ">="
         | 
| 154 155 | 
             
                - !ruby/object:Gem::Version
         | 
| 155 156 | 
             
                  version: '0'
         | 
| 156 157 | 
             
            required_rubygems_version: !ruby/object:Gem::Requirement
         | 
| 157 158 | 
             
              requirements:
         | 
| 158 | 
            -
              - -  | 
| 159 | 
            +
              - - ">="
         | 
| 159 160 | 
             
                - !ruby/object:Gem::Version
         | 
| 160 161 | 
             
                  version: '0'
         | 
| 161 162 | 
             
            requirements: []
         | 
| 162 163 | 
             
            rubyforge_project: 
         | 
| 163 | 
            -
            rubygems_version: 2.2. | 
| 164 | 
            +
            rubygems_version: 2.2.1
         | 
| 164 165 | 
             
            signing_key: 
         | 
| 165 166 | 
             
            specification_version: 4
         | 
| 166 167 | 
             
            summary: Domain-Oriented Refactoring Framework.
         | 
| 167 168 | 
             
            test_files:
         | 
| 168 169 | 
             
            - test/active_record_test.rb
         | 
| 170 | 
            +
            - test/composition_test.rb
         | 
| 169 171 | 
             
            - test/facade_test.rb
         | 
| 170 172 | 
             
            - test/test_helper.rb
         | 
| 171 173 | 
             
            - test/twin/active_record_test.rb
         | 
| 172 174 | 
             
            - test/twin/composition_test.rb
         | 
| 173 175 | 
             
            - test/twin/twin_test.rb
         | 
| 176 | 
            +
            has_rdoc: 
         |