graph_mediator 0.2.2 → 0.2.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.
- data/README.rdoc +1 -1
 - data/graph_mediator.gemspec +4 -2
 - data/lib/graph_mediator.rb +87 -11
 - data/lib/graph_mediator/version.rb +1 -1
 - data/spec/dependents/child.rb +9 -0
 - data/spec/dependents/parent.rb +20 -0
 - data/spec/dependents/schema.rb +23 -0
 - data/spec/graph_mediator_spec.rb +8 -1
 - data/spec/integration/destroy_dependents_locking_tests_spec.rb +84 -0
 - metadata +81 -16
 
    
        data/README.rdoc
    CHANGED
    
    | 
         @@ -106,7 +106,7 @@ lock_version.  So if another transaction updates a child, root.lock_version 
     | 
|
| 
       106 
106 
     | 
    
         
             
            should increment, and the first transaction should raise a StaleObject error
         
     | 
| 
       107 
107 
     | 
    
         
             
            when it too tries to update the child.
         
     | 
| 
       108 
108 
     | 
    
         | 
| 
       109 
     | 
    
         
            -
            If you override  
     | 
| 
      
 109 
     | 
    
         
            +
            If you override save in the model hierarchy you are mediating, you must pass your 
         
     | 
| 
       110 
110 
     | 
    
         
             
            override as a block to super or it will occur outside of mediation:
         
     | 
| 
       111 
111 
     | 
    
         | 
| 
       112 
112 
     | 
    
         
             
              def save
         
     | 
    
        data/graph_mediator.gemspec
    CHANGED
    
    | 
         @@ -24,8 +24,10 @@ Gem::Specification.new do |s| 
     | 
|
| 
       24 
24 
     | 
    
         
             
              s.test_files = `git ls-files spec/*`.split("\n")
         
     | 
| 
       25 
25 
     | 
    
         | 
| 
       26 
26 
     | 
    
         
             
              s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
         
     | 
| 
       27 
     | 
    
         
            -
              s. 
     | 
| 
       28 
     | 
    
         
            -
              s. 
     | 
| 
      
 27 
     | 
    
         
            +
              s.add_development_dependency(%q<diff-lcs>)
         
     | 
| 
      
 28 
     | 
    
         
            +
              s.add_development_dependency(%q<sqlite3>)
         
     | 
| 
      
 29 
     | 
    
         
            +
              s.add_runtime_dependency(%q<activerecord>, [">= 2.3.6", "< 3.0.0"])
         
     | 
| 
      
 30 
     | 
    
         
            +
              s.add_runtime_dependency(%q<activesupport>, [">= 2.3.6", "< 3.0.0"])
         
     | 
| 
       29 
31 
     | 
    
         
             
              s.add_runtime_dependency(%q<aasm>, [">= 2.2.0"])
         
     | 
| 
       30 
32 
     | 
    
         
             
            end
         
     | 
| 
       31 
33 
     | 
    
         | 
    
        data/lib/graph_mediator.rb
    CHANGED
    
    | 
         @@ -80,6 +80,9 @@ module GraphMediator 
     | 
|
| 
       80 
80 
     | 
    
         
             
                  base.__send__(:class_inheritable_array, :graph_mediator_dependencies)
         
     | 
| 
       81 
81 
     | 
    
         
             
                  base.graph_mediator_dependencies = []
         
     | 
| 
       82 
82 
     | 
    
         
             
                  base.__send__(:_register_for_mediation, *(SAVE_METHODS.clone << { :track_changes => true }))
         
     | 
| 
      
 83 
     | 
    
         
            +
                  base.class_eval do 
         
     | 
| 
      
 84 
     | 
    
         
            +
                    _alias_method_chain_ensuring_inheritability(:destroy, :flag)
         
     | 
| 
      
 85 
     | 
    
         
            +
                  end
         
     | 
| 
       83 
86 
     | 
    
         
             
                end
         
     | 
| 
       84 
87 
     | 
    
         | 
| 
       85 
88 
     | 
    
         
             
                # Inserts a new #{base}::MediatorProxy module with Proxy included.
         
     | 
| 
         @@ -104,10 +107,12 @@ module GraphMediator 
     | 
|
| 
       104 
107 
     | 
    
         
             
                  key = base.to_s.underscore.gsub('/','_').upcase
         
     | 
| 
       105 
108 
     | 
    
         
             
                  hash_key = "GRAPH_MEDIATOR_#{key}_HASH_KEY"
         
     | 
| 
       106 
109 
     | 
    
         
             
                  new_array_key = "GRAPH_MEDIATOR_#{key}_NEW_ARRAY_KEY"
         
     | 
| 
      
 110 
     | 
    
         
            +
                  being_destroyed_array_key = "GRAPH_MEDIATOR_#{key}_BEING_DESTROYED_ARRAY_KEY"
         
     | 
| 
       107 
111 
     | 
    
         
             
                  eigen = base.instance_eval { class << self; self; end }
         
     | 
| 
       108 
112 
     | 
    
         
             
                  eigen.class_eval do
         
     | 
| 
       109 
113 
     | 
    
         
             
                    define_method(:mediator_hash_key) { hash_key }
         
     | 
| 
       110 
114 
     | 
    
         
             
                    define_method(:mediator_new_array_key) { new_array_key }
         
     | 
| 
      
 115 
     | 
    
         
            +
                    define_method(:mediator_being_destroyed_array_key) { being_destroyed_array_key }
         
     | 
| 
       111 
116 
     | 
    
         
             
                  end
         
     | 
| 
       112 
117 
     | 
    
         | 
| 
       113 
118 
     | 
    
         
             
                  # Relies on ActiveSupport::Callbacks (which is included
         
     | 
| 
         @@ -189,27 +194,38 @@ module GraphMediator 
     | 
|
| 
       189 
194 
     | 
    
         
             
                  # (This is overwritten by GraphMediator._include_new_proxy)
         
     | 
| 
       190 
195 
     | 
    
         
             
                  def mediator_new_array_key; end
         
     | 
| 
       191 
196 
     | 
    
         | 
| 
      
 197 
     | 
    
         
            +
                  # Unique key to access a thread local array of ids of instances that
         
     | 
| 
      
 198 
     | 
    
         
            +
                  # are currently in the process of being deleted.
         
     | 
| 
      
 199 
     | 
    
         
            +
                  def mediator_being_destroyed_array_key; end
         
     | 
| 
      
 200 
     | 
    
         
            +
             
     | 
| 
       192 
201 
     | 
    
         
             
                  # The hash of Mediator instances active in this Thread for the Proxy's 
         
     | 
| 
       193 
202 
     | 
    
         
             
                  # base class.
         
     | 
| 
       194 
203 
     | 
    
         
             
                  #
         
     | 
| 
       195 
204 
     | 
    
         
             
                  # instance.id => Mediator of (instance)
         
     | 
| 
       196 
205 
     | 
    
         
             
                  #
         
     | 
| 
       197 
206 
     | 
    
         
             
                  def mediators
         
     | 
| 
       198 
     | 
    
         
            -
                     
     | 
| 
       199 
     | 
    
         
            -
                      Thread.current[mediator_hash_key] = {}
         
     | 
| 
       200 
     | 
    
         
            -
                    end
         
     | 
| 
       201 
     | 
    
         
            -
                    Thread.current[mediator_hash_key]
         
     | 
| 
      
 207 
     | 
    
         
            +
                    _generate_thread_local(mediator_hash_key, Hash)
         
     | 
| 
       202 
208 
     | 
    
         
             
                  end
         
     | 
| 
       203 
209 
     | 
    
         | 
| 
       204 
210 
     | 
    
         
             
                  # An array of Mediator instances mediating new records in this Thread for
         
     | 
| 
       205 
211 
     | 
    
         
             
                  # the Proxy's base class.
         
     | 
| 
       206 
212 
     | 
    
         
             
                  def mediators_for_new_records
         
     | 
| 
       207 
     | 
    
         
            -
                     
     | 
| 
       208 
     | 
    
         
            -
                      Thread.current[mediator_new_array_key] = []
         
     | 
| 
       209 
     | 
    
         
            -
                    end
         
     | 
| 
       210 
     | 
    
         
            -
                    Thread.current[mediator_new_array_key]
         
     | 
| 
      
 213 
     | 
    
         
            +
                    _generate_thread_local(mediator_new_array_key, Array)
         
     | 
| 
       211 
214 
     | 
    
         
             
                  end
         
     | 
| 
       212 
215 
     | 
    
         | 
| 
      
 216 
     | 
    
         
            +
                  # An array of instance ids currently being in the process of being destroyed.
         
     | 
| 
      
 217 
     | 
    
         
            +
                  def instances_being_destroyed
         
     | 
| 
      
 218 
     | 
    
         
            +
                    _generate_thread_local(mediator_being_destroyed_array_key, Array)
         
     | 
| 
      
 219 
     | 
    
         
            +
                  end
         
     | 
| 
      
 220 
     | 
    
         
            +
             
     | 
| 
      
 221 
     | 
    
         
            +
                  private
         
     | 
| 
      
 222 
     | 
    
         
            +
             
     | 
| 
      
 223 
     | 
    
         
            +
                  def _generate_thread_local(key, initial)
         
     | 
| 
      
 224 
     | 
    
         
            +
                    unless Thread.current[key]
         
     | 
| 
      
 225 
     | 
    
         
            +
                      Thread.current[key] = initial.kind_of?(Class) ? initial.new : initial
         
     | 
| 
      
 226 
     | 
    
         
            +
                    end
         
     | 
| 
      
 227 
     | 
    
         
            +
                    Thread.current[key]
         
     | 
| 
      
 228 
     | 
    
         
            +
                  end
         
     | 
| 
       213 
229 
     | 
    
         
             
                end
         
     | 
| 
       214 
230 
     | 
    
         | 
| 
       215 
231 
     | 
    
         
             
                # Wraps the given block in a transaction and begins mediation. 
         
     | 
| 
         @@ -257,6 +273,42 @@ module GraphMediator 
     | 
|
| 
       257 
273 
     | 
    
         
             
                  @graph_mediator_mediation_disabled = false
         
     | 
| 
       258 
274 
     | 
    
         
             
                end
         
     | 
| 
       259 
275 
     | 
    
         | 
| 
      
 276 
     | 
    
         
            +
                # True if this instance is currently in the middle of being destroyed.  Set
         
     | 
| 
      
 277 
     | 
    
         
            +
                # by code slipped around the core ActiveRecord::Base#destroy via
         
     | 
| 
      
 278 
     | 
    
         
            +
                # destroy_with_flag.
         
     | 
| 
      
 279 
     | 
    
         
            +
                #
         
     | 
| 
      
 280 
     | 
    
         
            +
                # Used by dependents in the mediation process to check whether they should
         
     | 
| 
      
 281 
     | 
    
         
            +
                # update their root (see notes under the +mediate+ method).
         
     | 
| 
      
 282 
     | 
    
         
            +
                def being_destroyed?
         
     | 
| 
      
 283 
     | 
    
         
            +
                  instances_being_destroyed.include?(id)  
         
     | 
| 
      
 284 
     | 
    
         
            +
                end
         
     | 
| 
      
 285 
     | 
    
         
            +
             
     | 
| 
      
 286 
     | 
    
         
            +
                # Surrounding the base destroy ensures that instance is marked in Thread
         
     | 
| 
      
 287 
     | 
    
         
            +
                # before any other callbacks occur (notably the collection destroy
         
     | 
| 
      
 288 
     | 
    
         
            +
                # dependents pushed into the before_destroy callback).
         
     | 
| 
      
 289 
     | 
    
         
            +
                #
         
     | 
| 
      
 290 
     | 
    
         
            +
                # If we instead relied on on the before_destroy, after_destroy callbacks,
         
     | 
| 
      
 291 
     | 
    
         
            +
                # we would be at the mercy of declaration order in the class for the
         
     | 
| 
      
 292 
     | 
    
         
            +
                # GraphMediator include versus the association macro.
         
     | 
| 
      
 293 
     | 
    
         
            +
                def destroy_with_flag
         
     | 
| 
      
 294 
     | 
    
         
            +
                  _mark_being_destroyed
         
     | 
| 
      
 295 
     | 
    
         
            +
                  destroy_without_flag
         
     | 
| 
      
 296 
     | 
    
         
            +
                ensure
         
     | 
| 
      
 297 
     | 
    
         
            +
                  _unmark_being_destroyed
         
     | 
| 
      
 298 
     | 
    
         
            +
                end
         
     | 
| 
      
 299 
     | 
    
         
            +
             
     | 
| 
      
 300 
     | 
    
         
            +
                private
         
     | 
| 
      
 301 
     | 
    
         
            +
             
     | 
| 
      
 302 
     | 
    
         
            +
                def _mark_being_destroyed
         
     | 
| 
      
 303 
     | 
    
         
            +
                  instances_being_destroyed << id
         
     | 
| 
      
 304 
     | 
    
         
            +
                end
         
     | 
| 
      
 305 
     | 
    
         
            +
             
     | 
| 
      
 306 
     | 
    
         
            +
                def _unmark_being_destroyed
         
     | 
| 
      
 307 
     | 
    
         
            +
                  instances_being_destroyed.delete(id) 
         
     | 
| 
      
 308 
     | 
    
         
            +
                end
         
     | 
| 
      
 309 
     | 
    
         
            +
             
     | 
| 
      
 310 
     | 
    
         
            +
                public
         
     | 
| 
      
 311 
     | 
    
         
            +
             
     | 
| 
       260 
312 
     | 
    
         
             
                # By default, every instance will be mediated and this will return true.
         
     | 
| 
       261 
313 
     | 
    
         
             
                # You can turn mediation on or off on an instance by instance basis with
         
     | 
| 
       262 
314 
     | 
    
         
             
                # calls to disable_mediation! or enable_mediation!.
         
     | 
| 
         @@ -295,6 +347,10 @@ module GraphMediator 
     | 
|
| 
       295 
347 
     | 
    
         
             
                  self.class.mediators_for_new_records
         
     | 
| 
       296 
348 
     | 
    
         
             
                end
         
     | 
| 
       297 
349 
     | 
    
         | 
| 
      
 350 
     | 
    
         
            +
                def instances_being_destroyed
         
     | 
| 
      
 351 
     | 
    
         
            +
                  self.class.instances_being_destroyed
         
     | 
| 
      
 352 
     | 
    
         
            +
                end
         
     | 
| 
      
 353 
     | 
    
         
            +
             
     | 
| 
       298 
354 
     | 
    
         
             
                # Accessor for the mediator associated with this instance's id, or nil if
         
     | 
| 
       299 
355 
     | 
    
         
             
                # we are not currently mediating.
         
     | 
| 
       300 
356 
     | 
    
         
             
                def current_mediator
         
     | 
| 
         @@ -335,7 +391,8 @@ module GraphMediator 
     | 
|
| 
       335 
391 
     | 
    
         
             
                #
         
     | 
| 
       336 
392 
     | 
    
         
             
                # * options:
         
     | 
| 
       337 
393 
     | 
    
         
             
                #   * :through => root node accessor that will be the target of the
         
     | 
| 
       338 
     | 
    
         
            -
                #     mediated_transaction.  By default self is assumed.
         
     | 
| 
      
 394 
     | 
    
         
            +
                #     mediated_transaction.  By default self is assumed.  This is used for
         
     | 
| 
      
 395 
     | 
    
         
            +
                #     tracking in the given root node the fact that dependents have changed.
         
     | 
| 
       339 
396 
     | 
    
         
             
                #   * :track_changes => if true, the mediator will track changes such
         
     | 
| 
       340 
397 
     | 
    
         
             
                #     that they can be reviewed after_mediation.  The after_mediation
         
     | 
| 
       341 
398 
     | 
    
         
             
                #     callbacks occur after dirty has completed and changes are normally
         
     | 
| 
         @@ -351,7 +408,7 @@ module GraphMediator 
     | 
|
| 
       351 
408 
     | 
    
         
             
                    _alias_method_chain_ensuring_inheritability(method, :mediation) do |aliased_target,punctuation|
         
     | 
| 
       352 
409 
     | 
    
         
             
                      __send__(:define_method, "#{aliased_target}_with_mediation#{punctuation}") do |*args, &block|
         
     | 
| 
       353 
410 
     | 
    
         
             
                        root_node = (root_node_accessor ? send(root_node_accessor) : self)
         
     | 
| 
       354 
     | 
    
         
            -
                        unless root_node.nil?
         
     | 
| 
      
 411 
     | 
    
         
            +
                        unless root_node.nil? || root_node.being_destroyed?
         
     | 
| 
       355 
412 
     | 
    
         
             
                          root_node.mediated_transaction do |mediator|
         
     | 
| 
       356 
413 
     | 
    
         
             
                            mediator.debug("#{root_node} mediating #{aliased_target}#{punctuation} for #{self}")
         
     | 
| 
       357 
414 
     | 
    
         
             
                            mediator.track_changes_for(self) if track_changes && saveing
         
     | 
| 
         @@ -485,7 +542,26 @@ module GraphMediator 
     | 
|
| 
       485 
542 
     | 
    
         
             
                # Dependent classes have their save methods mediated as well.  However, a
         
     | 
| 
       486 
543 
     | 
    
         
             
                # dependent class must provide an accessor for the root node, so that a
         
     | 
| 
       487 
544 
     | 
    
         
             
                # mediated_transaction can be begun in the root node when a dependent is
         
     | 
| 
       488 
     | 
    
         
            -
                # changed.
         
     | 
| 
      
 545 
     | 
    
         
            +
                # changed.  Dependent clases also have their destroy methods mediated so
         
     | 
| 
      
 546 
     | 
    
         
            +
                # that destruction of a dependent also registers as a change to the 
         
     | 
| 
      
 547 
     | 
    
         
            +
                # graph.
         
     | 
| 
      
 548 
     | 
    
         
            +
                # 
         
     | 
| 
      
 549 
     | 
    
         
            +
                # == Deletion and Dependents
         
     | 
| 
      
 550 
     | 
    
         
            +
                # 
         
     | 
| 
      
 551 
     | 
    
         
            +
                # When a class participating in mediation assigns a dependent to mediation,
         
     | 
| 
      
 552 
     | 
    
         
            +
                # destruction of that dependent class will cause an update to the parent's
         
     | 
| 
      
 553 
     | 
    
         
            +
                # lock_version.  This can cause a problem in Rails 2.3.6+ because
         
     | 
| 
      
 554 
     | 
    
         
            +
                # ActiveRecord#destroy is wrapped with an optimistic locking check.  When
         
     | 
| 
      
 555 
     | 
    
         
            +
                # the dependent association is set to :dependent => :destroy, the
         
     | 
| 
      
 556 
     | 
    
         
            +
                # dependents are automatically destroyed before the parent, which causes
         
     | 
| 
      
 557 
     | 
    
         
            +
                # graph_mediator to update the lock_version of the parent, which then fails
         
     | 
| 
      
 558 
     | 
    
         
            +
                # the optimistic locking check when it is sent for destruction in
         
     | 
| 
      
 559 
     | 
    
         
            +
                # ActiveRecord::Locking::Optimistic#destroy_with_lock.
         
     | 
| 
      
 560 
     | 
    
         
            +
                # 
         
     | 
| 
      
 561 
     | 
    
         
            +
                # To avoid this, GraphMediator causes an activerecord instance to flag when
         
     | 
| 
      
 562 
     | 
    
         
            +
                # it is in the process of destroying itself.  This flag is then checked by
         
     | 
| 
      
 563 
     | 
    
         
            +
                # dependents so they can bypass touching the parent when they are being
         
     | 
| 
      
 564 
     | 
    
         
            +
                # destroyed.
         
     | 
| 
       489 
565 
     | 
    
         
             
                #
         
     | 
| 
       490 
566 
     | 
    
         
             
                # = Versioning and Optimistic Locking
         
     | 
| 
       491 
567 
     | 
    
         
             
                #
         
     | 
| 
         @@ -0,0 +1,20 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Dependents
         
     | 
| 
      
 2 
     | 
    
         
            +
              class Parent < ActiveRecord::Base
         
     | 
| 
      
 3 
     | 
    
         
            +
                include GraphMediator
         
     | 
| 
      
 4 
     | 
    
         
            +
                mediate :dependencies => Child
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                has_many :children, :dependent => :destroy
         
     | 
| 
      
 7 
     | 
    
         
            +
              end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
              # To test whether the order of declaration impacts function
         
     | 
| 
      
 10 
     | 
    
         
            +
              # For example, if we used before_destroy callbacks to mark a parent
         
     | 
| 
      
 11 
     | 
    
         
            +
              # as being destroyed, the order matters, because associations register
         
     | 
| 
      
 12 
     | 
    
         
            +
              # themselves for deletion when first declared using before_destroy as
         
     | 
| 
      
 13 
     | 
    
         
            +
              # well.
         
     | 
| 
      
 14 
     | 
    
         
            +
              class ReverseParent < ActiveRecord::Base
         
     | 
| 
      
 15 
     | 
    
         
            +
                has_many :reverse_children, :dependent => :destroy
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                include GraphMediator
         
     | 
| 
      
 18 
     | 
    
         
            +
                mediate :dependencies => ReverseChild
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,23 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            create_schema do |connection|
         
     | 
| 
      
 2 
     | 
    
         
            +
              connection.create_table(:parents, :force => true) do |t|
         
     | 
| 
      
 3 
     | 
    
         
            +
                t.string :name
         
     | 
| 
      
 4 
     | 
    
         
            +
                t.integer :lock_version, :default => 0
         
     | 
| 
      
 5 
     | 
    
         
            +
                t.timestamps
         
     | 
| 
      
 6 
     | 
    
         
            +
              end
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
              connection.create_table(:reverse_parents, :force => true) do |t|
         
     | 
| 
      
 9 
     | 
    
         
            +
                t.string :name
         
     | 
| 
      
 10 
     | 
    
         
            +
                t.integer :lock_version, :default => 0
         
     | 
| 
      
 11 
     | 
    
         
            +
                t.timestamps
         
     | 
| 
      
 12 
     | 
    
         
            +
              end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              connection.create_table(:children, :force => true) do |t|
         
     | 
| 
      
 15 
     | 
    
         
            +
                t.integer :parent_id
         
     | 
| 
      
 16 
     | 
    
         
            +
                t.string :marker
         
     | 
| 
      
 17 
     | 
    
         
            +
              end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              connection.create_table(:reverse_children, :force => true) do |t|
         
     | 
| 
      
 20 
     | 
    
         
            +
                t.integer :reverse_parent_id
         
     | 
| 
      
 21 
     | 
    
         
            +
                t.string :marker
         
     | 
| 
      
 22 
     | 
    
         
            +
              end
         
     | 
| 
      
 23 
     | 
    
         
            +
            end
         
     | 
    
        data/spec/graph_mediator_spec.rb
    CHANGED
    
    | 
         @@ -485,7 +485,11 @@ describe "GraphMediator" do 
     | 
|
| 
       485 
485 
     | 
    
         
             
                it "should generate a unique mediator_new_array_key for each MediatorProxy" do
         
     | 
| 
       486 
486 
     | 
    
         
             
                  @f.class.mediator_new_array_key.should == 'GRAPH_MEDIATOR_GRAPH_MEDIATOR_SPEC_FOO_NEW_ARRAY_KEY'
         
     | 
| 
       487 
487 
     | 
    
         
             
                end
         
     | 
| 
       488 
     | 
    
         
            -
             
     | 
| 
      
 488 
     | 
    
         
            +
             
     | 
| 
      
 489 
     | 
    
         
            +
                it "should generate a unique mediator_being_destroyed_array_key for each MediatorProxy" do
         
     | 
| 
      
 490 
     | 
    
         
            +
                  @f.class.mediator_being_destroyed_array_key.should == 'GRAPH_MEDIATOR_GRAPH_MEDIATOR_SPEC_FOO_BEING_DESTROYED_ARRAY_KEY'
         
     | 
| 
      
 491 
     | 
    
         
            +
                end
         
     | 
| 
      
 492 
     | 
    
         
            +
             
     | 
| 
       489 
493 
     | 
    
         
             
                it "should access an array of mediators for new records" do
         
     | 
| 
       490 
494 
     | 
    
         
             
                  @f.__send__(:mediators_for_new_records).should == []
         
     | 
| 
       491 
495 
     | 
    
         
             
                end
         
     | 
| 
         @@ -494,6 +498,9 @@ describe "GraphMediator" do 
     | 
|
| 
       494 
498 
     | 
    
         
             
                  @f.__send__(:mediators).should == {}
         
     | 
| 
       495 
499 
     | 
    
         
             
                end
         
     | 
| 
       496 
500 
     | 
    
         | 
| 
      
 501 
     | 
    
         
            +
                it "should access an array of ids for instances being destroyed" do
         
     | 
| 
      
 502 
     | 
    
         
            +
                  @f.__send__(:instances_being_destroyed).should == []
         
     | 
| 
      
 503 
     | 
    
         
            +
                end
         
     | 
| 
       497 
504 
     | 
    
         
             
              end
         
     | 
| 
       498 
505 
     | 
    
         
             
            end
         
     | 
| 
       499 
506 
     | 
    
         | 
| 
         @@ -0,0 +1,84 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'dependents/child.rb'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'dependents/parent.rb'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            module Dependents
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
              describe "GraphMediator instances should flag that they are being destroyed" do
         
     | 
| 
      
 9 
     | 
    
         
            +
                def load_track_destroy
         
     | 
| 
      
 10 
     | 
    
         
            +
                  create_schema do |conn|
         
     | 
| 
      
 11 
     | 
    
         
            +
                    conn.create_table(:track_destroys, :force => true) do |t|
         
     | 
| 
      
 12 
     | 
    
         
            +
                      t.string :name
         
     | 
| 
      
 13 
     | 
    
         
            +
                      t.integer :lock_version, :defaults => 0
         
     | 
| 
      
 14 
     | 
    
         
            +
                      t.tiimestamps
         
     | 
| 
      
 15 
     | 
    
         
            +
                    end
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  @destroy_callbacks = callbacks_ref = []
         
     | 
| 
      
 19 
     | 
    
         
            +
                  c = Class.new(ActiveRecord::Base)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  Object.const_set(:TrackDestroy, c)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  c.class_eval do 
         
     | 
| 
      
 22 
     | 
    
         
            +
                    include GraphMediator
         
     | 
| 
      
 23 
     | 
    
         
            +
                    
         
     | 
| 
      
 24 
     | 
    
         
            +
                    def destroy_without_callbacks
         
     | 
| 
      
 25 
     | 
    
         
            +
                      callbacks << being_destroyed?
         
     | 
| 
      
 26 
     | 
    
         
            +
                      super
         
     | 
| 
      
 27 
     | 
    
         
            +
                    end
         
     | 
| 
      
 28 
     | 
    
         
            +
                    define_method(:callbacks) { callbacks_ref }
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
                end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                before(:each) do
         
     | 
| 
      
 33 
     | 
    
         
            +
                  load_track_destroy
         
     | 
| 
      
 34 
     | 
    
         
            +
                  @t = TrackDestroy.create!
         
     | 
| 
      
 35 
     | 
    
         
            +
                end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                it "should note that it is being destroyed" do
         
     | 
| 
      
 38 
     | 
    
         
            +
                  @t.should_not be_being_destroyed
         
     | 
| 
      
 39 
     | 
    
         
            +
                  @t.destroy
         
     | 
| 
      
 40 
     | 
    
         
            +
                  @destroy_callbacks.should == [true]
         
     | 
| 
      
 41 
     | 
    
         
            +
                  @t.should_not be_being_destroyed
         
     | 
| 
      
 42 
     | 
    
         
            +
                  @t.should be_destroyed
         
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
              end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
              describe "Tests ability to destroy objects with dependents despite optimistic locking" do
         
     | 
| 
      
 47 
     | 
    
         
            +
              
         
     | 
| 
      
 48 
     | 
    
         
            +
                before(:all) do
         
     | 
| 
      
 49 
     | 
    
         
            +
                  load 'dependents/schema.rb'
         
     | 
| 
      
 50 
     | 
    
         
            +
                end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                before(:each) do
         
     | 
| 
      
 53 
     | 
    
         
            +
                  @p = Parent.create!(:name => 'foo')
         
     | 
| 
      
 54 
     | 
    
         
            +
                  @c1 = @p.children.create(:marker => 'bar')
         
     | 
| 
      
 55 
     | 
    
         
            +
                  @c2 = @p.children.create(:marker => 'baz')
         
     | 
| 
      
 56 
     | 
    
         
            +
                end  
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                it "should not raise a stale object error when deleting a parent with dependents that are automagically destroyed by activerecord" do
         
     | 
| 
      
 59 
     | 
    
         
            +
                  @p.should_not be_new_record
         
     | 
| 
      
 60 
     | 
    
         
            +
                  @c1.should_not be_new_record
         
     | 
| 
      
 61 
     | 
    
         
            +
                  @c2.should_not be_new_record
         
     | 
| 
      
 62 
     | 
    
         
            +
                  @p.reload
         
     | 
| 
      
 63 
     | 
    
         
            +
                  lambda { @p.destroy }.should_not raise_error(ActiveRecord::StaleObjectError)
         
     | 
| 
      
 64 
     | 
    
         
            +
                end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                it "does not matter whether the include or association is declared first" do
         
     | 
| 
      
 67 
     | 
    
         
            +
                  rp = ReverseParent.create(:name => 'foo')
         
     | 
| 
      
 68 
     | 
    
         
            +
                  c1 = rp.reverse_children.create(:marker => 'bar')
         
     | 
| 
      
 69 
     | 
    
         
            +
                  c2 = rp.reverse_children.create(:marker => 'baz')
         
     | 
| 
      
 70 
     | 
    
         
            +
                  rp.reload
         
     | 
| 
      
 71 
     | 
    
         
            +
                  lambda { rp.destroy }.should_not raise_error(ActiveRecord::StaleObjectError)
         
     | 
| 
      
 72 
     | 
    
         
            +
                end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
      
 74 
     | 
    
         
            +
                # This is a vague test that our changes to destroy workflow don't choke
         
     | 
| 
      
 75 
     | 
    
         
            +
                # in the trivial case of an unstored instance.
         
     | 
| 
      
 76 
     | 
    
         
            +
                it "should be okay if call destroy on new object" do
         
     | 
| 
      
 77 
     | 
    
         
            +
                  np = Parent.new(:name => 'foo')
         
     | 
| 
      
 78 
     | 
    
         
            +
                  cp = np.children.new(:marker => 'bar')
         
     | 
| 
      
 79 
     | 
    
         
            +
                  np.destroy.should == np # Nothing should be thrown
         
     | 
| 
      
 80 
     | 
    
         
            +
                  np.should be_destroyed
         
     | 
| 
      
 81 
     | 
    
         
            +
                  np.lock_version.should == 0
         
     | 
| 
      
 82 
     | 
    
         
            +
                end
         
     | 
| 
      
 83 
     | 
    
         
            +
              end
         
     | 
| 
      
 84 
     | 
    
         
            +
            end
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,12 +1,13 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification 
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: graph_mediator
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version 
         
     | 
| 
      
 4 
     | 
    
         
            +
              hash: 17
         
     | 
| 
       4 
5 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       5 
6 
     | 
    
         
             
              segments: 
         
     | 
| 
       6 
7 
     | 
    
         
             
              - 0
         
     | 
| 
       7 
8 
     | 
    
         
             
              - 2
         
     | 
| 
       8 
     | 
    
         
            -
              -  
     | 
| 
       9 
     | 
    
         
            -
              version: 0.2. 
     | 
| 
      
 9 
     | 
    
         
            +
              - 3
         
     | 
| 
      
 10 
     | 
    
         
            +
              version: 0.2.3
         
     | 
| 
       10 
11 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       11 
12 
     | 
    
         
             
            authors: 
         
     | 
| 
       12 
13 
     | 
    
         
             
            - Josh Partlow
         
     | 
| 
         @@ -14,16 +15,18 @@ autorequire: 
     | 
|
| 
       14 
15 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       15 
16 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       16 
17 
     | 
    
         | 
| 
       17 
     | 
    
         
            -
            date:  
     | 
| 
      
 18 
     | 
    
         
            +
            date: 2013-01-24 00:00:00 -08:00
         
     | 
| 
       18 
19 
     | 
    
         
             
            default_executable: 
         
     | 
| 
       19 
20 
     | 
    
         
             
            dependencies: 
         
     | 
| 
       20 
21 
     | 
    
         
             
            - !ruby/object:Gem::Dependency 
         
     | 
| 
       21 
22 
     | 
    
         
             
              name: rspec
         
     | 
| 
       22 
23 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       23 
24 
     | 
    
         
             
              requirement: &id001 !ruby/object:Gem::Requirement 
         
     | 
| 
      
 25 
     | 
    
         
            +
                none: false
         
     | 
| 
       24 
26 
     | 
    
         
             
                requirements: 
         
     | 
| 
       25 
27 
     | 
    
         
             
                - - ">="
         
     | 
| 
       26 
28 
     | 
    
         
             
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 29 
     | 
    
         
            +
                    hash: 13
         
     | 
| 
       27 
30 
     | 
    
         
             
                    segments: 
         
     | 
| 
       28 
31 
     | 
    
         
             
                    - 1
         
     | 
| 
       29 
32 
     | 
    
         
             
                    - 2
         
     | 
| 
         @@ -32,47 +35,97 @@ dependencies: 
     | 
|
| 
       32 
35 
     | 
    
         
             
              type: :development
         
     | 
| 
       33 
36 
     | 
    
         
             
              version_requirements: *id001
         
     | 
| 
       34 
37 
     | 
    
         
             
            - !ruby/object:Gem::Dependency 
         
     | 
| 
       35 
     | 
    
         
            -
              name:  
     | 
| 
      
 38 
     | 
    
         
            +
              name: diff-lcs
         
     | 
| 
       36 
39 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       37 
40 
     | 
    
         
             
              requirement: &id002 !ruby/object:Gem::Requirement 
         
     | 
| 
      
 41 
     | 
    
         
            +
                none: false
         
     | 
| 
       38 
42 
     | 
    
         
             
                requirements: 
         
     | 
| 
       39 
     | 
    
         
            -
                - - " 
     | 
| 
      
 43 
     | 
    
         
            +
                - - ">="
         
     | 
| 
       40 
44 
     | 
    
         
             
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 45 
     | 
    
         
            +
                    hash: 3
         
     | 
| 
      
 46 
     | 
    
         
            +
                    segments: 
         
     | 
| 
      
 47 
     | 
    
         
            +
                    - 0
         
     | 
| 
      
 48 
     | 
    
         
            +
                    version: "0"
         
     | 
| 
      
 49 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 50 
     | 
    
         
            +
              version_requirements: *id002
         
     | 
| 
      
 51 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency 
         
     | 
| 
      
 52 
     | 
    
         
            +
              name: sqlite3
         
     | 
| 
      
 53 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 54 
     | 
    
         
            +
              requirement: &id003 !ruby/object:Gem::Requirement 
         
     | 
| 
      
 55 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 56 
     | 
    
         
            +
                requirements: 
         
     | 
| 
      
 57 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 58 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 59 
     | 
    
         
            +
                    hash: 3
         
     | 
| 
      
 60 
     | 
    
         
            +
                    segments: 
         
     | 
| 
      
 61 
     | 
    
         
            +
                    - 0
         
     | 
| 
      
 62 
     | 
    
         
            +
                    version: "0"
         
     | 
| 
      
 63 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 64 
     | 
    
         
            +
              version_requirements: *id003
         
     | 
| 
      
 65 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency 
         
     | 
| 
      
 66 
     | 
    
         
            +
              name: activerecord
         
     | 
| 
      
 67 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 68 
     | 
    
         
            +
              requirement: &id004 !ruby/object:Gem::Requirement 
         
     | 
| 
      
 69 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 70 
     | 
    
         
            +
                requirements: 
         
     | 
| 
      
 71 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 72 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 73 
     | 
    
         
            +
                    hash: 15
         
     | 
| 
       41 
74 
     | 
    
         
             
                    segments: 
         
     | 
| 
       42 
75 
     | 
    
         
             
                    - 2
         
     | 
| 
       43 
76 
     | 
    
         
             
                    - 3
         
     | 
| 
       44 
     | 
    
         
            -
                    -  
     | 
| 
       45 
     | 
    
         
            -
                    version: 2.3. 
     | 
| 
      
 77 
     | 
    
         
            +
                    - 6
         
     | 
| 
      
 78 
     | 
    
         
            +
                    version: 2.3.6
         
     | 
| 
      
 79 
     | 
    
         
            +
                - - <
         
     | 
| 
      
 80 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 81 
     | 
    
         
            +
                    hash: 7
         
     | 
| 
      
 82 
     | 
    
         
            +
                    segments: 
         
     | 
| 
      
 83 
     | 
    
         
            +
                    - 3
         
     | 
| 
      
 84 
     | 
    
         
            +
                    - 0
         
     | 
| 
      
 85 
     | 
    
         
            +
                    - 0
         
     | 
| 
      
 86 
     | 
    
         
            +
                    version: 3.0.0
         
     | 
| 
       46 
87 
     | 
    
         
             
              type: :runtime
         
     | 
| 
       47 
     | 
    
         
            -
              version_requirements: * 
     | 
| 
      
 88 
     | 
    
         
            +
              version_requirements: *id004
         
     | 
| 
       48 
89 
     | 
    
         
             
            - !ruby/object:Gem::Dependency 
         
     | 
| 
       49 
90 
     | 
    
         
             
              name: activesupport
         
     | 
| 
       50 
91 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       51 
     | 
    
         
            -
              requirement: & 
     | 
| 
      
 92 
     | 
    
         
            +
              requirement: &id005 !ruby/object:Gem::Requirement 
         
     | 
| 
      
 93 
     | 
    
         
            +
                none: false
         
     | 
| 
       52 
94 
     | 
    
         
             
                requirements: 
         
     | 
| 
       53 
     | 
    
         
            -
                - - " 
     | 
| 
      
 95 
     | 
    
         
            +
                - - ">="
         
     | 
| 
       54 
96 
     | 
    
         
             
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 97 
     | 
    
         
            +
                    hash: 15
         
     | 
| 
       55 
98 
     | 
    
         
             
                    segments: 
         
     | 
| 
       56 
99 
     | 
    
         
             
                    - 2
         
     | 
| 
       57 
100 
     | 
    
         
             
                    - 3
         
     | 
| 
       58 
     | 
    
         
            -
                    -  
     | 
| 
       59 
     | 
    
         
            -
                    version: 2.3. 
     | 
| 
      
 101 
     | 
    
         
            +
                    - 6
         
     | 
| 
      
 102 
     | 
    
         
            +
                    version: 2.3.6
         
     | 
| 
      
 103 
     | 
    
         
            +
                - - <
         
     | 
| 
      
 104 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 105 
     | 
    
         
            +
                    hash: 7
         
     | 
| 
      
 106 
     | 
    
         
            +
                    segments: 
         
     | 
| 
      
 107 
     | 
    
         
            +
                    - 3
         
     | 
| 
      
 108 
     | 
    
         
            +
                    - 0
         
     | 
| 
      
 109 
     | 
    
         
            +
                    - 0
         
     | 
| 
      
 110 
     | 
    
         
            +
                    version: 3.0.0
         
     | 
| 
       60 
111 
     | 
    
         
             
              type: :runtime
         
     | 
| 
       61 
     | 
    
         
            -
              version_requirements: * 
     | 
| 
      
 112 
     | 
    
         
            +
              version_requirements: *id005
         
     | 
| 
       62 
113 
     | 
    
         
             
            - !ruby/object:Gem::Dependency 
         
     | 
| 
       63 
114 
     | 
    
         
             
              name: aasm
         
     | 
| 
       64 
115 
     | 
    
         
             
              prerelease: false
         
     | 
| 
       65 
     | 
    
         
            -
              requirement: & 
     | 
| 
      
 116 
     | 
    
         
            +
              requirement: &id006 !ruby/object:Gem::Requirement 
         
     | 
| 
      
 117 
     | 
    
         
            +
                none: false
         
     | 
| 
       66 
118 
     | 
    
         
             
                requirements: 
         
     | 
| 
       67 
119 
     | 
    
         
             
                - - ">="
         
     | 
| 
       68 
120 
     | 
    
         
             
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 121 
     | 
    
         
            +
                    hash: 7
         
     | 
| 
       69 
122 
     | 
    
         
             
                    segments: 
         
     | 
| 
       70 
123 
     | 
    
         
             
                    - 2
         
     | 
| 
       71 
124 
     | 
    
         
             
                    - 2
         
     | 
| 
       72 
125 
     | 
    
         
             
                    - 0
         
     | 
| 
       73 
126 
     | 
    
         
             
                    version: 2.2.0
         
     | 
| 
       74 
127 
     | 
    
         
             
              type: :runtime
         
     | 
| 
       75 
     | 
    
         
            -
              version_requirements: * 
     | 
| 
      
 128 
     | 
    
         
            +
              version_requirements: *id006
         
     | 
| 
       76 
129 
     | 
    
         
             
            description: Mediates state changes between a set of interdependent ActiveRecord objects.
         
     | 
| 
       77 
130 
     | 
    
         
             
            email: jpartlow@glatisant.org
         
     | 
| 
       78 
131 
     | 
    
         
             
            executables: []
         
     | 
| 
         @@ -94,10 +147,14 @@ files: 
     | 
|
| 
       94 
147 
     | 
    
         
             
            - lib/graph_mediator/mediator.rb
         
     | 
| 
       95 
148 
     | 
    
         
             
            - lib/graph_mediator/version.rb
         
     | 
| 
       96 
149 
     | 
    
         
             
            - spec/database.rb
         
     | 
| 
      
 150 
     | 
    
         
            +
            - spec/dependents/child.rb
         
     | 
| 
      
 151 
     | 
    
         
            +
            - spec/dependents/parent.rb
         
     | 
| 
      
 152 
     | 
    
         
            +
            - spec/dependents/schema.rb
         
     | 
| 
       97 
153 
     | 
    
         
             
            - spec/examples/course_example_spec.rb
         
     | 
| 
       98 
154 
     | 
    
         
             
            - spec/examples/dingo_pen_example_spec.rb
         
     | 
| 
       99 
155 
     | 
    
         
             
            - spec/graph_mediator_spec.rb
         
     | 
| 
       100 
156 
     | 
    
         
             
            - spec/integration/changes_spec.rb
         
     | 
| 
      
 157 
     | 
    
         
            +
            - spec/integration/destroy_dependents_locking_tests_spec.rb
         
     | 
| 
       101 
158 
     | 
    
         
             
            - spec/integration/locking_tests_spec.rb
         
     | 
| 
       102 
159 
     | 
    
         
             
            - spec/integration/nesting_spec.rb
         
     | 
| 
       103 
160 
     | 
    
         
             
            - spec/integration/threads_spec.rb
         
     | 
| 
         @@ -127,16 +184,20 @@ rdoc_options: 
     | 
|
| 
       127 
184 
     | 
    
         
             
            require_paths: 
         
     | 
| 
       128 
185 
     | 
    
         
             
            - lib
         
     | 
| 
       129 
186 
     | 
    
         
             
            required_ruby_version: !ruby/object:Gem::Requirement 
         
     | 
| 
      
 187 
     | 
    
         
            +
              none: false
         
     | 
| 
       130 
188 
     | 
    
         
             
              requirements: 
         
     | 
| 
       131 
189 
     | 
    
         
             
              - - ">="
         
     | 
| 
       132 
190 
     | 
    
         
             
                - !ruby/object:Gem::Version 
         
     | 
| 
      
 191 
     | 
    
         
            +
                  hash: 3
         
     | 
| 
       133 
192 
     | 
    
         
             
                  segments: 
         
     | 
| 
       134 
193 
     | 
    
         
             
                  - 0
         
     | 
| 
       135 
194 
     | 
    
         
             
                  version: "0"
         
     | 
| 
       136 
195 
     | 
    
         
             
            required_rubygems_version: !ruby/object:Gem::Requirement 
         
     | 
| 
      
 196 
     | 
    
         
            +
              none: false
         
     | 
| 
       137 
197 
     | 
    
         
             
              requirements: 
         
     | 
| 
       138 
198 
     | 
    
         
             
              - - ">="
         
     | 
| 
       139 
199 
     | 
    
         
             
                - !ruby/object:Gem::Version 
         
     | 
| 
      
 200 
     | 
    
         
            +
                  hash: 23
         
     | 
| 
       140 
201 
     | 
    
         
             
                  segments: 
         
     | 
| 
       141 
202 
     | 
    
         
             
                  - 1
         
     | 
| 
       142 
203 
     | 
    
         
             
                  - 3
         
     | 
| 
         @@ -145,16 +206,20 @@ required_rubygems_version: !ruby/object:Gem::Requirement 
     | 
|
| 
       145 
206 
     | 
    
         
             
            requirements: []
         
     | 
| 
       146 
207 
     | 
    
         | 
| 
       147 
208 
     | 
    
         
             
            rubyforge_project: 
         
     | 
| 
       148 
     | 
    
         
            -
            rubygems_version: 1.3. 
     | 
| 
      
 209 
     | 
    
         
            +
            rubygems_version: 1.3.7
         
     | 
| 
       149 
210 
     | 
    
         
             
            signing_key: 
         
     | 
| 
       150 
211 
     | 
    
         
             
            specification_version: 3
         
     | 
| 
       151 
212 
     | 
    
         
             
            summary: Mediates ActiveRecord state changes
         
     | 
| 
       152 
213 
     | 
    
         
             
            test_files: 
         
     | 
| 
       153 
214 
     | 
    
         
             
            - spec/database.rb
         
     | 
| 
      
 215 
     | 
    
         
            +
            - spec/dependents/child.rb
         
     | 
| 
      
 216 
     | 
    
         
            +
            - spec/dependents/parent.rb
         
     | 
| 
      
 217 
     | 
    
         
            +
            - spec/dependents/schema.rb
         
     | 
| 
       154 
218 
     | 
    
         
             
            - spec/examples/course_example_spec.rb
         
     | 
| 
       155 
219 
     | 
    
         
             
            - spec/examples/dingo_pen_example_spec.rb
         
     | 
| 
       156 
220 
     | 
    
         
             
            - spec/graph_mediator_spec.rb
         
     | 
| 
       157 
221 
     | 
    
         
             
            - spec/integration/changes_spec.rb
         
     | 
| 
      
 222 
     | 
    
         
            +
            - spec/integration/destroy_dependents_locking_tests_spec.rb
         
     | 
| 
       158 
223 
     | 
    
         
             
            - spec/integration/locking_tests_spec.rb
         
     | 
| 
       159 
224 
     | 
    
         
             
            - spec/integration/nesting_spec.rb
         
     | 
| 
       160 
225 
     | 
    
         
             
            - spec/integration/threads_spec.rb
         
     |