couchbase-model-relationship 0.1.13 → 0.1.14

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,6 +2,7 @@ module Couchbase
2
2
  class Model
3
3
  module Relationship
4
4
  module Child
5
+
5
6
  extend ::ActiveSupport::Concern
6
7
 
7
8
  def create_with_parent_id(options = {})
@@ -9,8 +10,28 @@ module Couchbase
9
10
  @id = prefixed_id(parent.id)
10
11
  end
11
12
 
12
- create_without_parent_id(options)
13
+ # Should this only fire if we had a parent and assigned the id?
14
+ retried = false
15
+ begin
16
+ create_without_parent_id(options)
17
+ rescue Couchbase::Error::KeyExists => error
18
+ if !retried && ok_to_merge_on_key_exists_error?
19
+ retried = true
20
+ on_key_exists_merge_from_db!
21
+
22
+ retry
23
+ end
24
+
25
+ raise error
26
+ end
27
+ end
28
+
29
+ def ok_to_merge_on_key_exists_error?
30
+ respond_to?(:on_key_exists_merge_from_db!) &&
31
+ parent.present? &&
32
+ id == prefixed_id(parent.id)
13
33
  end
34
+ private :ok_to_merge_on_key_exists_error?
14
35
 
15
36
  module ClassMethods
16
37
  def has_parent
@@ -1,7 +1,7 @@
1
1
  module Couchbase
2
2
  class Model
3
3
  module Relationship
4
- VERSION = "0.1.13"
4
+ VERSION = "0.1.14"
5
5
  end
6
6
  end
7
7
  end
data/spec/child_spec.rb CHANGED
@@ -4,6 +4,13 @@ class ChildTest < Couchbase::Model
4
4
  has_parent
5
5
  end
6
6
 
7
+ class ChildMergeTest < Couchbase::Model
8
+ has_parent
9
+
10
+ def on_key_exists_merge_from_db!
11
+ end
12
+ end
13
+
7
14
  class ChildTestParent < Couchbase::Model
8
15
  child :child_test
9
16
  end
@@ -29,5 +36,67 @@ describe "children" do
29
36
 
30
37
  subject.id.should eq("child_test:1234")
31
38
  end
39
+
40
+ describe "with collisions" do
41
+ let(:collider) { ChildMergeTest.new(parent: parent) }
42
+ let(:bucket) { stub }
43
+
44
+ before do
45
+ parent.id = "parent:#{Time.now.to_i}"
46
+ ChildMergeTest.stubs(bucket: bucket)
47
+ end
48
+
49
+ it "just fails if no merge method" do
50
+ bucket.expects(:add).raises(Couchbase::Error::KeyExists)
51
+ ChildTest.stubs(bucket: bucket)
52
+
53
+ expect { subject.save }.to raise_error(Couchbase::Error::KeyExists)
54
+ end
55
+
56
+ it "just fails with no parent" do
57
+ bucket.expects(:add).raises(Couchbase::Error::KeyExists)
58
+
59
+ collider.parent = nil
60
+ collider.expects(:on_key_exists_merge_from_db!).never
61
+
62
+ expect { collider.save }.to raise_error(Couchbase::Error::KeyExists)
63
+ end
64
+
65
+ it "just fails with a parent and a non-parent derived id" do
66
+ collider.instance_variable_set(:@id, "abc123:1234")
67
+ bucket.expects(:add).raises(Couchbase::Error::KeyExists)
68
+ collider.expects(:on_key_exists_merge_from_db!).never
69
+
70
+ expect { collider.save }.to raise_error(Couchbase::Error::KeyExists)
71
+ end
72
+
73
+ # These should really exercise a real backend
74
+ it "retries if mergable" do
75
+ seq = sequence("collision")
76
+ bucket.expects(:add).raises(Couchbase::Error::KeyExists).in_sequence(seq)
77
+ bucket.expects(:add).returns(true).in_sequence(seq)
78
+
79
+ collider.expects(:on_key_exists_merge_from_db!)
80
+
81
+ expect { collider.save }.to_not raise_error
82
+ collider.should be_persisted
83
+ end
84
+
85
+ it "fails is merging fails" do
86
+ bucket.expects(:add).raises(Couchbase::Error::KeyExists)
87
+
88
+ collider.expects(:on_key_exists_merge_from_db!).raises(ArgumentError)
89
+
90
+ expect { collider.save }.to raise_error(ArgumentError)
91
+ end
92
+
93
+ it "only retries once" do
94
+ bucket.expects(:add).raises(Couchbase::Error::KeyExists).twice
95
+
96
+ collider.expects(:on_key_exists_merge_from_db!)
97
+
98
+ expect { collider.save }.to raise_error(Couchbase::Error::KeyExists)
99
+ end
100
+ end
32
101
  end
33
102
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: couchbase-model-relationship
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.13
4
+ version: 0.1.14
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-05-29 00:00:00.000000000 Z
12
+ date: 2014-06-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activemodel
@@ -218,7 +218,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
218
218
  version: '0'
219
219
  segments:
220
220
  - 0
221
- hash: -924479147595009082
221
+ hash: -1698513283546959422
222
222
  required_rubygems_version: !ruby/object:Gem::Requirement
223
223
  none: false
224
224
  requirements:
@@ -227,7 +227,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
227
227
  version: '0'
228
228
  segments:
229
229
  - 0
230
- hash: -924479147595009082
230
+ hash: -1698513283546959422
231
231
  requirements: []
232
232
  rubyforge_project:
233
233
  rubygems_version: 1.8.24