ripple 0.9.5 → 1.0.0.beta
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +32 -0
- data/Gemfile +10 -9
- data/Guardfile +15 -0
- data/Rakefile +11 -40
- data/lib/rails/generators/ripple/configuration/configuration_generator.rb +0 -13
- data/lib/rails/generators/ripple/configuration/templates/ripple.yml +4 -4
- data/lib/rails/generators/ripple/js/js_generator.rb +0 -13
- data/lib/rails/generators/ripple/js/templates/js/contrib.js +0 -17
- data/lib/rails/generators/ripple/js/templates/js/ripple.js +0 -13
- data/lib/rails/generators/ripple/model/model_generator.rb +0 -14
- data/lib/rails/generators/ripple/model/templates/model.rb +1 -1
- data/lib/rails/generators/ripple/observer/observer_generator.rb +0 -14
- data/lib/rails/generators/ripple/test/test_generator.rb +7 -19
- data/lib/rails/generators/ripple_generator.rb +1 -14
- data/lib/ripple.rb +7 -14
- data/lib/ripple/associations.rb +129 -26
- data/lib/ripple/associations/embedded.rb +1 -15
- data/lib/ripple/associations/instantiators.rb +0 -13
- data/lib/ripple/associations/linked.rb +41 -19
- data/lib/ripple/associations/many.rb +0 -14
- data/lib/ripple/associations/many_embedded_proxy.rb +0 -14
- data/lib/ripple/associations/many_linked_proxy.rb +39 -18
- data/lib/ripple/associations/many_reference_proxy.rb +93 -0
- data/lib/ripple/associations/many_stored_key_proxy.rb +76 -0
- data/lib/ripple/associations/one.rb +1 -15
- data/lib/ripple/associations/one_embedded_proxy.rb +0 -14
- data/lib/ripple/associations/one_key_proxy.rb +58 -0
- data/lib/ripple/associations/one_linked_proxy.rb +4 -14
- data/lib/ripple/associations/one_stored_key_proxy.rb +43 -0
- data/lib/ripple/associations/proxy.rb +8 -14
- data/lib/ripple/attribute_methods.rb +19 -17
- data/lib/ripple/attribute_methods/dirty.rb +19 -15
- data/lib/ripple/attribute_methods/query.rb +0 -14
- data/lib/ripple/attribute_methods/read.rb +0 -14
- data/lib/ripple/attribute_methods/write.rb +0 -14
- data/lib/ripple/callbacks.rb +10 -16
- data/lib/ripple/conflict/basic_resolver.rb +82 -0
- data/lib/ripple/conflict/document_hooks.rb +20 -0
- data/lib/ripple/conflict/resolver.rb +71 -0
- data/lib/ripple/conflict/test_helper.rb +33 -0
- data/lib/ripple/conversion.rb +0 -14
- data/lib/ripple/core_ext.rb +1 -14
- data/lib/ripple/core_ext/casting.rb +19 -19
- data/lib/ripple/core_ext/object.rb +8 -0
- data/lib/ripple/document.rb +21 -16
- data/lib/ripple/document/bucket_access.rb +0 -14
- data/lib/ripple/document/finders.rb +17 -23
- data/lib/ripple/document/key.rb +8 -28
- data/lib/ripple/document/link.rb +30 -0
- data/lib/ripple/document/persistence.rb +12 -20
- data/lib/ripple/embedded_document.rb +10 -15
- data/lib/ripple/embedded_document/around_callbacks.rb +18 -0
- data/lib/ripple/embedded_document/finders.rb +7 -18
- data/lib/ripple/embedded_document/persistence.rb +5 -17
- data/lib/ripple/i18n.rb +0 -14
- data/lib/ripple/inspection.rb +21 -15
- data/lib/ripple/locale/en.yml +9 -13
- data/lib/ripple/nested_attributes.rb +33 -39
- data/lib/ripple/observable.rb +0 -13
- data/lib/ripple/properties.rb +1 -14
- data/lib/ripple/property_type_mismatch.rb +0 -14
- data/lib/ripple/railtie.rb +4 -14
- data/lib/ripple/railties/ripple.rake +86 -0
- data/lib/ripple/serialization.rb +11 -11
- data/lib/ripple/test_server.rb +36 -0
- data/lib/ripple/timestamps.rb +0 -13
- data/lib/ripple/translation.rb +4 -14
- data/lib/ripple/validations.rb +1 -15
- data/lib/ripple/validations/associated_validator.rb +26 -17
- data/lib/ripple/version.rb +3 -0
- data/ripple.gemspec +24 -35
- data/spec/integration/ripple/associations_spec.rb +89 -58
- data/spec/integration/ripple/conflict_resolution_spec.rb +298 -0
- data/spec/integration/ripple/nested_attributes_spec.rb +19 -19
- data/spec/integration/ripple/persistence_spec.rb +15 -34
- data/spec/integration/ripple/search_associations_spec.rb +31 -0
- data/spec/ripple/associations/many_embedded_proxy_spec.rb +23 -36
- data/spec/ripple/associations/many_linked_proxy_spec.rb +133 -45
- data/spec/ripple/associations/many_reference_proxy_spec.rb +170 -0
- data/spec/ripple/associations/many_stored_key_proxy_spec.rb +158 -0
- data/spec/ripple/associations/one_embedded_proxy_spec.rb +24 -37
- data/spec/ripple/associations/one_key_proxy_spec.rb +82 -0
- data/spec/ripple/associations/one_linked_proxy_spec.rb +22 -23
- data/spec/ripple/associations/one_stored_key_proxy_spec.rb +72 -0
- data/spec/ripple/associations/proxy_spec.rb +21 -15
- data/spec/ripple/associations_spec.rb +54 -23
- data/spec/ripple/attribute_methods/dirty_spec.rb +56 -5
- data/spec/ripple/attribute_methods_spec.rb +47 -21
- data/spec/ripple/bucket_access_spec.rb +4 -17
- data/spec/ripple/callbacks_spec.rb +52 -15
- data/spec/ripple/conflict/resolver_spec.rb +42 -0
- data/spec/ripple/conversion_spec.rb +2 -15
- data/spec/ripple/core_ext_spec.rb +12 -15
- data/spec/ripple/document/link_spec.rb +67 -0
- data/spec/ripple/document_spec.rb +34 -19
- data/spec/ripple/embedded_document/finders_spec.rb +12 -19
- data/spec/ripple/embedded_document/persistence_spec.rb +20 -26
- data/spec/ripple/embedded_document_spec.rb +44 -34
- data/spec/ripple/finders_spec.rb +58 -29
- data/spec/ripple/inspection_spec.rb +40 -37
- data/spec/ripple/key_spec.rb +5 -17
- data/spec/ripple/observable_spec.rb +3 -16
- data/spec/ripple/persistence_spec.rb +134 -18
- data/spec/ripple/properties_spec.rb +21 -15
- data/spec/ripple/ripple_spec.rb +1 -14
- data/spec/ripple/serialization_spec.rb +16 -17
- data/spec/ripple/timestamps_spec.rb +73 -52
- data/spec/ripple/validations/associated_validator_spec.rb +69 -25
- data/spec/ripple/validations_spec.rb +3 -16
- data/spec/spec_helper.rb +17 -18
- data/spec/support/associations.rb +1 -1
- data/spec/support/associations/proxies.rb +0 -13
- data/spec/support/integration_setup.rb +11 -0
- data/spec/support/mocks.rb +0 -13
- data/spec/support/models.rb +33 -2
- data/spec/support/models/address.rb +1 -16
- data/spec/support/models/box.rb +7 -14
- data/spec/support/models/car.rb +27 -1
- data/spec/support/models/cardboard_box.rb +0 -14
- data/spec/support/models/clock.rb +6 -15
- data/spec/support/models/clock_observer.rb +0 -14
- data/spec/support/models/credit_card.rb +5 -0
- data/spec/support/models/customer.rb +0 -14
- data/spec/support/models/email.rb +0 -14
- data/spec/support/models/family.rb +1 -13
- data/spec/support/models/favorite.rb +0 -14
- data/spec/support/models/invoice.rb +0 -14
- data/spec/support/models/late_invoice.rb +0 -14
- data/spec/support/models/nested.rb +12 -0
- data/spec/support/models/ninja.rb +7 -0
- data/spec/support/models/note.rb +0 -14
- data/spec/support/models/page.rb +1 -15
- data/spec/support/models/paid_invoice.rb +0 -14
- data/spec/support/models/post.rb +12 -0
- data/spec/support/models/profile.rb +7 -0
- data/spec/support/models/subscription.rb +26 -0
- data/spec/support/models/tasks.rb +0 -18
- data/spec/support/models/team.rb +11 -0
- data/spec/support/models/transactions.rb +17 -0
- data/spec/support/models/tree.rb +2 -16
- data/spec/support/models/user.rb +14 -16
- data/spec/support/models/widget.rb +8 -14
- data/spec/support/search.rb +14 -0
- data/spec/support/test_server.rb +22 -12
- data/spec/support/test_server.yml.example +14 -2
- metadata +223 -59
- data/lib/rails/generators/ripple/test/templates/test_server.rb +0 -46
- data/spec/support/models/driver.rb +0 -5
- data/spec/support/models/engine.rb +0 -4
- data/spec/support/models/passenger.rb +0 -5
- data/spec/support/models/seat.rb +0 -4
- data/spec/support/models/wheel.rb +0 -5
@@ -1,14 +1,13 @@
|
|
1
|
-
require
|
1
|
+
require 'spec_helper'
|
2
2
|
require 'active_support/core_ext/array'
|
3
3
|
|
4
|
-
describe Ripple::NestedAttributes do
|
5
|
-
require 'support/models/car'
|
6
|
-
require 'support/models/driver'
|
7
|
-
require 'support/models/passenger'
|
8
|
-
require 'support/models/engine'
|
9
|
-
require 'support/models/seat'
|
10
|
-
require 'support/models/wheel'
|
11
|
-
require 'support/test_server'
|
4
|
+
describe Ripple::NestedAttributes, :integration => true do
|
5
|
+
# require 'support/models/car'
|
6
|
+
# require 'support/models/driver'
|
7
|
+
# require 'support/models/passenger'
|
8
|
+
# require 'support/models/engine'
|
9
|
+
# require 'support/models/seat'
|
10
|
+
# require 'support/models/wheel'
|
12
11
|
|
13
12
|
context "one :driver (link)" do
|
14
13
|
subject { Car.new }
|
@@ -93,10 +92,9 @@ describe Ripple::NestedAttributes do
|
|
93
92
|
end
|
94
93
|
|
95
94
|
it "should save the children when saving the parent" do
|
96
|
-
subject.passengers.each do |passenger|
|
97
|
-
passenger.should_receive(:save)
|
98
|
-
end
|
99
95
|
subject.save
|
96
|
+
found_subject = Car.find(subject.key)
|
97
|
+
found_subject.passengers.map(&:name).should =~ %w[ Joe Sue Pat ]
|
100
98
|
end
|
101
99
|
end
|
102
100
|
|
@@ -134,12 +132,16 @@ describe Ripple::NestedAttributes do
|
|
134
132
|
|
135
133
|
it "should save the child when saving the parent" do
|
136
134
|
subject.passengers_attributes = [ { :key => passenger1.key, :name => 'UPDATED One' },
|
137
|
-
{ :key =>
|
138
|
-
{ :key =>
|
139
|
-
subject.passengers.each do |passenger|
|
140
|
-
passenger.should_receive(:save)
|
141
|
-
end
|
135
|
+
{ :key => passenger2.key, :name => 'UPDATED Two' },
|
136
|
+
{ :key => passenger3.key, :name => 'UPDATED Three' } ]
|
142
137
|
subject.save
|
138
|
+
|
139
|
+
found_subject = Car.find(subject.key)
|
140
|
+
found_subject.passengers.map(&:name).should =~ [
|
141
|
+
'UPDATED One',
|
142
|
+
'UPDATED Two',
|
143
|
+
'UPDATED Three'
|
144
|
+
]
|
143
145
|
end
|
144
146
|
end
|
145
147
|
end
|
@@ -255,7 +257,5 @@ describe Ripple::NestedAttributes do
|
|
255
257
|
subject.save
|
256
258
|
subject.wheels.should == []
|
257
259
|
end
|
258
|
-
|
259
260
|
end
|
260
|
-
|
261
261
|
end
|
@@ -1,41 +1,16 @@
|
|
1
|
-
|
2
|
-
#
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
-
# you may not use this file except in compliance with the License.
|
5
|
-
# You may obtain a copy of the License at
|
6
|
-
#
|
7
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
-
#
|
9
|
-
# Unless required by applicable law or agreed to in writing, software
|
10
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
-
# See the License for the specific language governing permissions and
|
13
|
-
# limitations under the License.
|
14
|
-
require File.expand_path("../../../spec_helper", __FILE__)
|
1
|
+
require 'spec_helper'
|
15
2
|
|
16
3
|
describe "Ripple Persistence" do
|
17
|
-
require 'support/test_server'
|
18
|
-
|
19
|
-
before :all do
|
20
|
-
Object.module_eval do
|
21
|
-
class Widget
|
22
|
-
include Ripple::Document
|
23
|
-
property :name, String
|
24
|
-
property :size, Integer
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
4
|
before :each do
|
30
5
|
@widget = Widget.new
|
31
6
|
end
|
32
|
-
|
7
|
+
|
33
8
|
it "should save an object to the riak database" do
|
34
9
|
@widget.save
|
35
10
|
@found = Widget.find(@widget.key)
|
36
11
|
@found.should be_a(Widget)
|
37
12
|
end
|
38
|
-
|
13
|
+
|
39
14
|
it "should save attributes properly to riak" do
|
40
15
|
@widget.attributes = {:name => 'Sprocket', :size => 10}
|
41
16
|
@widget.save
|
@@ -43,13 +18,19 @@ describe "Ripple Persistence" do
|
|
43
18
|
@found.name.should == 'Sprocket'
|
44
19
|
@found.size.should == 10
|
45
20
|
end
|
46
|
-
|
47
|
-
|
48
|
-
|
21
|
+
end
|
22
|
+
|
23
|
+
describe Ripple::Document do
|
24
|
+
let(:custom_data) { Subscription::MyCustomType.new('bar') }
|
25
|
+
let(:days_of_month) { Set.new([1, 7, 15, 23]) }
|
26
|
+
let(:subscription) { Subscription.create!(:custom_data => custom_data, :days_of_month => days_of_month) }
|
27
|
+
let(:found_subscription) { Subscription.find(subscription.key) }
|
28
|
+
|
29
|
+
it 'allows properties with custom types to be saved and restored from riak' do
|
30
|
+
found_subscription.custom_data.should == custom_data
|
49
31
|
end
|
50
32
|
|
51
|
-
|
52
|
-
|
33
|
+
it 'allows Set properties to be saved and restored from riak' do
|
34
|
+
found_subscription.days_of_month.should == days_of_month
|
53
35
|
end
|
54
|
-
|
55
36
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Ripple Search Associations", :integration => true, :search => true do
|
4
|
+
class SearchTransaction
|
5
|
+
include Ripple::Document
|
6
|
+
property :search_account_key, String
|
7
|
+
property :name, String
|
8
|
+
end
|
9
|
+
|
10
|
+
class SearchAccount
|
11
|
+
include Ripple::Document
|
12
|
+
many :search_transactions, :using => :reference
|
13
|
+
property :email, String
|
14
|
+
end
|
15
|
+
|
16
|
+
before :each do
|
17
|
+
@account = SearchAccount.new(:email => 'riak@ripple.com')
|
18
|
+
@transaction1 = SearchTransaction.new(:name => 'One')
|
19
|
+
@transaction2 = SearchTransaction.new(:name => 'Two')
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should save a many referenced association" do
|
23
|
+
@account.save!
|
24
|
+
@account.search_transactions << @transaction1 << @transaction2
|
25
|
+
@transaction1.save!
|
26
|
+
@transaction2.save!
|
27
|
+
@found = SearchAccount.find(@account.key)
|
28
|
+
@found.search_transactions.map(&:key).should include(@transaction1.key)
|
29
|
+
@found.search_transactions.map(&:key).should include(@transaction2.key)
|
30
|
+
end
|
31
|
+
end
|
@@ -1,81 +1,68 @@
|
|
1
|
-
|
2
|
-
#
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
-
# you may not use this file except in compliance with the License.
|
5
|
-
# You may obtain a copy of the License at
|
6
|
-
#
|
7
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
-
#
|
9
|
-
# Unless required by applicable law or agreed to in writing, software
|
10
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
-
# See the License for the specific language governing permissions and
|
13
|
-
# limitations under the License.
|
14
|
-
require File.expand_path("../../../spec_helper", __FILE__)
|
1
|
+
require 'spec_helper'
|
15
2
|
|
16
3
|
describe Ripple::Associations::ManyEmbeddedProxy do
|
17
|
-
require 'support/models/user'
|
18
|
-
require 'support/models/address'
|
19
|
-
require 'support/models/note'
|
20
|
-
|
4
|
+
# require 'support/models/user'
|
5
|
+
# require 'support/models/address'
|
6
|
+
# require 'support/models/note'
|
7
|
+
|
21
8
|
before :each do
|
22
|
-
@user = User.new
|
9
|
+
@user = User.new(:email => "riak@ripple.com")
|
23
10
|
@address = Address.new
|
24
11
|
@addr = Address.new(:street => '123 Somewhere')
|
25
12
|
@note = Note.new
|
26
13
|
end
|
27
|
-
|
14
|
+
|
28
15
|
it "should not have children before any are set" do
|
29
16
|
@user.addresses.should == []
|
30
17
|
end
|
31
|
-
|
18
|
+
|
32
19
|
it "should be able to set and get its children" do
|
33
20
|
Address.stub!(:instantiate).and_return(@address)
|
34
21
|
@user.addresses = [@address]
|
35
22
|
@user.addresses.should == [@address]
|
36
23
|
end
|
37
|
-
|
24
|
+
|
38
25
|
it "should set the parent document on the children when assigning" do
|
39
26
|
@user.addresses = [@address]
|
40
27
|
@address._parent_document.should == @user
|
41
28
|
end
|
42
|
-
|
29
|
+
|
43
30
|
it "should return the assignment when assigning" do
|
44
31
|
rtn = @user.addresses = [@address]
|
45
32
|
rtn.should == [@address]
|
46
33
|
end
|
47
|
-
|
34
|
+
|
48
35
|
it "should set the parent document on the children when accessing" do
|
49
36
|
@user.addresses = [@address]
|
50
37
|
@user.addresses.first._parent_document.should == @user
|
51
38
|
end
|
52
|
-
|
39
|
+
|
53
40
|
it "should be able to replace its children with different children" do
|
54
41
|
@user.addresses = [@address]
|
55
42
|
@user.addresses.first.street.should be_blank
|
56
43
|
@user.addresses = [@addr]
|
57
44
|
@user.addresses.first.street.should == '123 Somewhere'
|
58
45
|
end
|
59
|
-
|
46
|
+
|
60
47
|
it "should be able to add to its children" do
|
61
48
|
Address.stub!(:instantiate).and_return(@address)
|
62
49
|
@user.addresses = [@address]
|
63
50
|
@user.addresses << @address
|
64
51
|
@user.addresses.should == [@address, @address]
|
65
52
|
end
|
66
|
-
|
53
|
+
|
67
54
|
it "should be able to chain calls to adding children" do
|
68
55
|
Address.stub!(:instantiate).and_return(@address)
|
69
56
|
@user.addresses = [@address]
|
70
57
|
@user.addresses << @address << @address << @address
|
71
58
|
@user.addresses.should == [@address, @address, @address, @address]
|
72
59
|
end
|
73
|
-
|
60
|
+
|
74
61
|
it "should set the parent document when adding to its children" do
|
75
62
|
@user.addresses << @address
|
76
63
|
@user.addresses.first._parent_document.should == @user
|
77
64
|
end
|
78
|
-
|
65
|
+
|
79
66
|
it "should be able to count its children" do
|
80
67
|
@user.addresses = [@address, @address]
|
81
68
|
@user.addresses.count.should == 2
|
@@ -85,37 +72,37 @@ describe Ripple::Associations::ManyEmbeddedProxy do
|
|
85
72
|
Address.stub!(:new).and_return(@address)
|
86
73
|
@user.addresses.build.should == @address
|
87
74
|
end
|
88
|
-
|
75
|
+
|
89
76
|
it "should assign a parent to the children created with instantiate_target" do
|
90
77
|
Address.stub!(:new).and_return(@address)
|
91
78
|
@address._parent_document.should be_nil
|
92
79
|
@user.addresses.build._parent_document.should == @user
|
93
80
|
end
|
94
|
-
|
81
|
+
|
95
82
|
it "should validate the children when saving the parent" do
|
96
83
|
@user.valid?.should be_true
|
97
84
|
@user.addresses << @address
|
98
85
|
@address.valid?.should be_false
|
99
86
|
@user.valid?.should be_false
|
100
87
|
end
|
101
|
-
|
88
|
+
|
102
89
|
it "should not save the root document when a child is invalid" do
|
103
90
|
@user.addresses << @address
|
104
91
|
@user.save.should be_false
|
105
92
|
end
|
106
|
-
|
93
|
+
|
107
94
|
it "should allow embedding documents in embedded documents" do
|
108
95
|
@user.addresses << @address
|
109
96
|
@address.notes << @note
|
110
97
|
@note._root_document.should == @user
|
111
98
|
@note._parent_document.should == @address
|
112
99
|
end
|
113
|
-
|
100
|
+
|
114
101
|
it "should allow assiging child documents as an array of hashes" do
|
115
102
|
@user.attributes = {'addresses' => [{'street' => '123 Somewhere'}]}
|
116
103
|
@user.addresses.first.street.should == '123 Somewhere'
|
117
104
|
end
|
118
|
-
|
105
|
+
|
119
106
|
it "should return an array from to_ary" do
|
120
107
|
Address.stub!(:instantiate).and_return(@address)
|
121
108
|
@user.addresses << @address
|
@@ -127,7 +114,7 @@ describe Ripple::Associations::ManyEmbeddedProxy do
|
|
127
114
|
lambda { @user.addresses = @address }.should raise_error
|
128
115
|
lambda { @user.addresses = [@note] }.should raise_error
|
129
116
|
end
|
130
|
-
|
117
|
+
|
131
118
|
it "should not add the associated validator multiple times" do
|
132
119
|
#$stderr.puts User.validators.collect(&:inspect)
|
133
120
|
User.validators_on(:addresses).count.should eq(1)
|
@@ -1,25 +1,13 @@
|
|
1
|
-
|
2
|
-
#
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
-
# you may not use this file except in compliance with the License.
|
5
|
-
# You may obtain a copy of the License at
|
6
|
-
#
|
7
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
-
#
|
9
|
-
# Unless required by applicable law or agreed to in writing, software
|
10
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
-
# See the License for the specific language governing permissions and
|
13
|
-
# limitations under the License.
|
14
|
-
require File.expand_path("../../../spec_helper", __FILE__)
|
1
|
+
require 'spec_helper'
|
15
2
|
|
16
3
|
describe Ripple::Associations::ManyLinkedProxy do
|
17
|
-
require 'support/models/tasks'
|
4
|
+
# require 'support/models/tasks'
|
18
5
|
|
19
6
|
before :each do
|
20
7
|
@person = Person.new {|p| p.key = "riak-user" }
|
21
8
|
@task = Task.new {|t| t.key = "one" }
|
22
9
|
@other_task = Task.new {|t| t.key = "two" }
|
10
|
+
@third_task = Task.new {|t| t.key = "three" }
|
23
11
|
[@person, @task, @other_task].each do |doc|
|
24
12
|
doc.stub!(:new?).and_return(false)
|
25
13
|
end
|
@@ -35,7 +23,13 @@ describe Ripple::Associations::ManyLinkedProxy do
|
|
35
23
|
|
36
24
|
it "should set the links on the RObject when assigning" do
|
37
25
|
@person.tasks = [@task]
|
38
|
-
@person.robject.links.should include(@task.
|
26
|
+
@person.robject.links.should include(@task.to_link("tasks"))
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should be able to replace the entire collection of documents (even appended ones)" do
|
30
|
+
@person.tasks << @task
|
31
|
+
@person.tasks = [@other_task]
|
32
|
+
@person.tasks.should == [@other_task]
|
39
33
|
end
|
40
34
|
|
41
35
|
it "should return the assigned documents when assigning" do
|
@@ -43,47 +37,39 @@ describe Ripple::Associations::ManyLinkedProxy do
|
|
43
37
|
t.should == [@task]
|
44
38
|
end
|
45
39
|
|
46
|
-
it "should save unsaved documents when assigning" do
|
47
|
-
@task.should_receive(:new?).and_return(true)
|
48
|
-
@task.should_receive(:save).and_return(true)
|
49
|
-
@person.tasks = [@task]
|
50
|
-
end
|
51
|
-
|
52
40
|
it "should link-walk to the associated documents when accessing" do
|
53
|
-
@person.robject.links << @task.
|
41
|
+
@person.robject.links << @task.to_link("tasks")
|
54
42
|
@person.robject.should_receive(:walk).with(Riak::WalkSpec.new(:bucket => "tasks", :tag => "tasks")).and_return([])
|
55
43
|
@person.tasks.should == []
|
56
44
|
end
|
57
45
|
|
58
|
-
it "
|
59
|
-
@person.tasks
|
60
|
-
@person.
|
61
|
-
|
62
|
-
|
46
|
+
it "handles conflict appropriately by selecting the linked-walk robjects that match the links" do
|
47
|
+
@person.robject.links << @task.to_link("tasks") << @other_task.to_link("tasks")
|
48
|
+
@person.robject.
|
49
|
+
should_receive(:walk).
|
50
|
+
with(Riak::WalkSpec.new(:bucket => "tasks", :tag => "tasks")).
|
51
|
+
and_return([[@task.robject, @other_task.robject, @third_task.robject]])
|
63
52
|
|
64
|
-
|
65
|
-
@person.tasks << @task
|
66
|
-
@person.tasks << @other_task
|
67
|
-
@person.should have(2).tasks
|
53
|
+
@person.tasks.should == [@task, @other_task]
|
68
54
|
end
|
69
55
|
|
70
|
-
it "
|
71
|
-
@person.tasks
|
72
|
-
@person.
|
56
|
+
it "allows the links to be replaced directly" do
|
57
|
+
@person.tasks = [@task]
|
58
|
+
@person.tasks.__send__(:should_receive, :reset)
|
59
|
+
@person.tasks.__send__(:links).should == [@task.robject.to_link("tasks")]
|
60
|
+
@person.tasks.replace_links([@other_task, @third_task].map { |t| t.robject.to_link("tasks") })
|
61
|
+
@person.tasks.__send__(:links).should == [@other_task, @third_task].map { |t| t.robject.to_link("tasks") }
|
73
62
|
end
|
74
63
|
|
75
|
-
it "should
|
76
|
-
@person.tasks
|
77
|
-
|
78
|
-
|
79
|
-
end
|
64
|
+
it "should replace associated documents with a new set" do
|
65
|
+
@person.tasks = [@task]
|
66
|
+
@person.tasks = [@other_task]
|
67
|
+
@person.tasks.should == [@other_task]
|
80
68
|
end
|
81
69
|
|
82
|
-
it "
|
83
|
-
@person.tasks
|
84
|
-
@person.tasks.count.should ==
|
85
|
-
@person.tasks << @other_task
|
86
|
-
@person.tasks.count.should == 2
|
70
|
+
it "asks the keys set for the count to avoid having to unnecessarily load all documents" do
|
71
|
+
@person.tasks.keys.stub(:size => 17)
|
72
|
+
@person.tasks.count.should == 17
|
87
73
|
end
|
88
74
|
|
89
75
|
# it "should be able to build a new associated document" do
|
@@ -100,4 +86,106 @@ describe Ripple::Associations::ManyLinkedProxy do
|
|
100
86
|
lambda { @person.tasks = @task }.should raise_error
|
101
87
|
lambda { @person.tasks = [@person] }.should raise_error
|
102
88
|
end
|
89
|
+
|
90
|
+
describe "#<< (when the target has not already been loaded)" do
|
91
|
+
it "avoids link-walking when adding a record to an unloaded association" do
|
92
|
+
@person.robject.should_not_receive(:walk)
|
93
|
+
@person.tasks << @task
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should be able to count the associated documents" do
|
97
|
+
@person.tasks << @task
|
98
|
+
@person.tasks.count.should == 1
|
99
|
+
@person.tasks << @other_task
|
100
|
+
@person.tasks.count.should == 2
|
101
|
+
end
|
102
|
+
|
103
|
+
it "maintains the list of keys properly as new documents are appended" do
|
104
|
+
@person.tasks << @task
|
105
|
+
@person.tasks.should have(1).key
|
106
|
+
@person.tasks << @other_task
|
107
|
+
@person.tasks.should have(2).keys
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should be able to append documents to the associated set" do
|
111
|
+
@person.tasks << @task
|
112
|
+
@person.tasks << @other_task
|
113
|
+
@person.should have(2).tasks
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should be able to chain calls to adding documents" do
|
117
|
+
@person.tasks << @task << @other_task
|
118
|
+
@person.should have(2).tasks
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should set the links on the RObject when appending" do
|
122
|
+
@person.tasks << @task << @other_task
|
123
|
+
[@task, @other_task].each do |t|
|
124
|
+
@person.robject.links.should include(t.to_link("tasks"))
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
it "does not return duplicates (for when the object has been appended and it's robject is found while walking the links)" do
|
129
|
+
@person.tasks.stub(:robjects => [@task.robject])
|
130
|
+
@person.tasks.reset
|
131
|
+
@person.tasks << @task
|
132
|
+
@person.tasks.should == [@task]
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
describe "#reset" do
|
137
|
+
it "clears appended documents" do
|
138
|
+
@person.tasks << @task
|
139
|
+
@person.tasks.reset
|
140
|
+
@person.tasks.should == []
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
describe "#keys" do
|
145
|
+
let(:link_keys) { %w[ 1 2 3 ] }
|
146
|
+
let(:links) { link_keys.map { |k| Riak::Link.new('tasks', k, 'task') } }
|
147
|
+
|
148
|
+
before(:each) do
|
149
|
+
@person.tasks.stub(:links => links)
|
150
|
+
end
|
151
|
+
|
152
|
+
it "returns a set of keys" do
|
153
|
+
@person.tasks.keys.should be_a(Set)
|
154
|
+
@person.tasks.keys.to_a.should == link_keys
|
155
|
+
end
|
156
|
+
|
157
|
+
it "is memoized between calls" do
|
158
|
+
@person.tasks.keys.should equal(@person.tasks.keys)
|
159
|
+
end
|
160
|
+
|
161
|
+
it "is cleared when the association is reset" do
|
162
|
+
orig_set = @person.tasks.keys
|
163
|
+
@person.tasks.reset
|
164
|
+
@person.tasks.keys.should_not equal(orig_set)
|
165
|
+
end
|
166
|
+
|
167
|
+
it "is cleared when the association is replaced" do
|
168
|
+
orig_set = @person.tasks.keys
|
169
|
+
@person.tasks.replace([@task])
|
170
|
+
@person.tasks.keys.should_not equal(orig_set)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
describe "#include?" do
|
175
|
+
it "delegates to the set of keys so as not to unnecessarily load the associated documents" do
|
176
|
+
@person.tasks.keys.should_receive(:include?).with(@task.key).and_return(true)
|
177
|
+
@person.tasks.include?(@task).should be_true
|
178
|
+
end
|
179
|
+
|
180
|
+
it "short-circuits and returns false if the given object is not a ripple document" do
|
181
|
+
@person.tasks.keys.should_not_receive(:include?)
|
182
|
+
@person.tasks.include?(Object.new).should be_false
|
183
|
+
end
|
184
|
+
|
185
|
+
it "returns false if the document's bucket is different from the associations bucket, even if the keys are the same" do
|
186
|
+
@person.tasks << @task
|
187
|
+
other_person = Person.new { |p| p.key = @task.key }
|
188
|
+
@person.tasks.include?(other_person).should be_false
|
189
|
+
end
|
190
|
+
end
|
103
191
|
end
|