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
|