couchbase-model-relationship 0.1.13 → 0.1.14

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.
@@ -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