ripple 0.6.1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. data/Rakefile +61 -48
  2. data/lib/ripple.rb +5 -1
  3. data/lib/ripple/core_ext/casting.rb +3 -0
  4. data/lib/ripple/document.rb +6 -2
  5. data/lib/ripple/document/associations.rb +154 -0
  6. data/lib/ripple/document/{persistence/callbacks.rb → associations/embedded.rb} +20 -24
  7. data/lib/ripple/document/associations/instantiators.rb +41 -0
  8. data/lib/{riak/util/translation.rb → ripple/document/associations/linked.rb} +14 -11
  9. data/lib/ripple/document/associations/many.rb +52 -0
  10. data/lib/ripple/document/associations/many_embedded_proxy.rb +49 -0
  11. data/lib/{riak/i18n.rb → ripple/document/associations/one.rb} +18 -2
  12. data/lib/ripple/document/associations/one_embedded_proxy.rb +41 -0
  13. data/lib/ripple/document/associations/proxy.rb +125 -0
  14. data/lib/ripple/document/attribute_methods.rb +8 -1
  15. data/lib/ripple/document/attribute_methods/read.rb +4 -0
  16. data/lib/ripple/document/attribute_methods/write.rb +4 -0
  17. data/lib/ripple/document/bucket_access.rb +1 -1
  18. data/lib/ripple/document/callbacks.rb +75 -0
  19. data/lib/ripple/document/finders.rb +50 -3
  20. data/lib/ripple/document/persistence.rb +14 -6
  21. data/lib/ripple/document/validations.rb +35 -7
  22. data/lib/ripple/document/validations/associated_validator.rb +37 -0
  23. data/lib/ripple/embedded_document.rb +8 -2
  24. data/lib/{riak/map_reduce_error.rb → ripple/embedded_document/conversion.rb} +19 -5
  25. data/lib/{riak/invalid_response.rb → ripple/embedded_document/finders.rb} +17 -8
  26. data/lib/ripple/embedded_document/persistence.rb +75 -13
  27. data/lib/ripple/locale/en.yml +7 -1
  28. data/{spec/riak/net_http_backend_spec.rb → lib/ripple/railtie.rb} +17 -13
  29. data/spec/fixtures/config.yml +3 -0
  30. data/spec/integration/ripple/associations_spec.rb +81 -0
  31. data/spec/integration/ripple/persistence_spec.rb +54 -0
  32. data/spec/ripple/associations/many_embedded_proxy_spec.rb +124 -0
  33. data/spec/ripple/associations/one_embedded_proxy_spec.rb +130 -0
  34. data/spec/ripple/associations/proxy_spec.rb +78 -0
  35. data/spec/ripple/associations_spec.rb +111 -0
  36. data/spec/ripple/attribute_methods_spec.rb +37 -16
  37. data/spec/ripple/bucket_access_spec.rb +3 -14
  38. data/spec/ripple/callbacks_spec.rb +53 -9
  39. data/spec/ripple/document_spec.rb +22 -6
  40. data/spec/ripple/embedded_document/conversion_spec.rb +35 -0
  41. data/spec/{riak/headers_spec.rb → ripple/embedded_document/finders_spec.rb} +17 -14
  42. data/spec/ripple/embedded_document/persistence_spec.rb +86 -0
  43. data/spec/ripple/embedded_document_spec.rb +1 -26
  44. data/spec/ripple/finders_spec.rb +66 -30
  45. data/spec/ripple/persistence_spec.rb +33 -21
  46. data/spec/ripple/properties_spec.rb +1 -7
  47. data/spec/ripple/ripple_spec.rb +10 -0
  48. data/spec/ripple/timestamps_spec.rb +12 -19
  49. data/spec/ripple/validations_spec.rb +48 -6
  50. data/spec/spec_helper.rb +4 -10
  51. data/spec/support/associations/proxies.rb +16 -0
  52. data/spec/support/integration.rb +4 -0
  53. data/spec/support/mocks.rb +3 -0
  54. data/spec/support/models/address.rb +8 -0
  55. data/spec/support/models/box.rb +6 -0
  56. data/spec/support/models/cardboard_box.rb +3 -0
  57. data/spec/support/models/clock.rb +6 -0
  58. data/spec/support/models/customer.rb +4 -0
  59. data/spec/support/models/email.rb +4 -0
  60. data/spec/support/models/family.rb +14 -0
  61. data/spec/support/models/favorite.rb +4 -0
  62. data/spec/support/models/invoice.rb +6 -0
  63. data/spec/support/models/late_invoice.rb +3 -0
  64. data/spec/support/models/note.rb +4 -0
  65. data/spec/support/models/page.rb +4 -0
  66. data/spec/support/models/paid_invoice.rb +4 -0
  67. data/spec/support/models/tree.rb +3 -0
  68. data/spec/support/models/user.rb +6 -0
  69. data/spec/support/models/widget.rb +6 -0
  70. metadata +111 -138
  71. data/.document +0 -5
  72. data/.gitignore +0 -26
  73. data/CONTRIBUTORS.textile +0 -5
  74. data/LICENSE +0 -13
  75. data/README.textile +0 -128
  76. data/RELEASE_NOTES.textile +0 -68
  77. data/VERSION +0 -1
  78. data/lib/riak.rb +0 -46
  79. data/lib/riak/bucket.rb +0 -157
  80. data/lib/riak/client.rb +0 -139
  81. data/lib/riak/client/curb_backend.rb +0 -82
  82. data/lib/riak/client/http_backend.rb +0 -209
  83. data/lib/riak/client/net_http_backend.rb +0 -49
  84. data/lib/riak/failed_request.rb +0 -37
  85. data/lib/riak/link.rb +0 -73
  86. data/lib/riak/locale/en.yml +0 -37
  87. data/lib/riak/map_reduce.rb +0 -248
  88. data/lib/riak/robject.rb +0 -258
  89. data/lib/riak/util/escape.rb +0 -12
  90. data/lib/riak/util/fiber1.8.rb +0 -48
  91. data/lib/riak/util/headers.rb +0 -44
  92. data/lib/riak/util/multipart.rb +0 -52
  93. data/lib/riak/walk_spec.rb +0 -117
  94. data/ripple.gemspec +0 -169
  95. data/spec/fixtures/cat.jpg +0 -0
  96. data/spec/fixtures/multipart-blank.txt +0 -7
  97. data/spec/fixtures/multipart-with-body.txt +0 -16
  98. data/spec/riak/bucket_spec.rb +0 -230
  99. data/spec/riak/client_spec.rb +0 -174
  100. data/spec/riak/curb_backend_spec.rb +0 -50
  101. data/spec/riak/escape_spec.rb +0 -17
  102. data/spec/riak/http_backend_spec.rb +0 -131
  103. data/spec/riak/link_spec.rb +0 -82
  104. data/spec/riak/map_reduce_spec.rb +0 -352
  105. data/spec/riak/multipart_spec.rb +0 -36
  106. data/spec/riak/object_spec.rb +0 -532
  107. data/spec/riak/walk_spec_spec.rb +0 -208
  108. data/spec/spec.opts +0 -1
  109. data/spec/support/http_backend_implementation_examples.rb +0 -215
  110. data/spec/support/mock_server.rb +0 -58
@@ -0,0 +1,3 @@
1
+ ripple:
2
+ port: 9000
3
+ host: localhost
@@ -0,0 +1,81 @@
1
+ # Copyright 2010 Sean Cribbs, Sonian Inc., and Basho Technologies, Inc.
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__)
15
+
16
+ describe "Ripple Associations" do
17
+ before :all do
18
+ switch_to_test_node
19
+ Object.module_eval do
20
+ class User
21
+ include Ripple::Document
22
+ one :profile
23
+ many :addresses
24
+ property :email, String, :presence => true
25
+ end
26
+ class Profile
27
+ include Ripple::EmbeddedDocument
28
+ property :name, String, :presence => true
29
+ embedded_in :user
30
+ end
31
+ class Address
32
+ include Ripple::EmbeddedDocument
33
+ property :street, String, :presence => true
34
+ property :kind, String, :presence => true
35
+ embedded_in :user
36
+ end
37
+ end
38
+ end
39
+
40
+ before :each do
41
+ @user = User.new(:email => 'riak@ripple.com')
42
+ @profile = Profile.new(:name => 'Ripple')
43
+ @billing = Address.new(:street => '123 Somewhere Dr', :kind => 'billing')
44
+ @shipping = Address.new(:street => '321 Anywhere Pl', :kind => 'shipping')
45
+ end
46
+
47
+ it "should save one embedded associations" do
48
+ @user.profile = @profile
49
+ @user.save
50
+ @found = User.find(@user.key)
51
+ @found.profile.name.should == 'Ripple'
52
+ @found.profile.should be_a(Profile)
53
+ @found.profile.user.should == @found
54
+ end
55
+
56
+ it "should save many embedded associations" do
57
+ @user.addresses << @billing << @shipping
58
+ @user.save
59
+ @found = User.find(@user.key)
60
+ @found.addresses.count.should == 2
61
+ @bill = @found.addresses.detect {|a| a.kind == 'billing'}
62
+ @ship = @found.addresses.detect {|a| a.kind == 'shipping'}
63
+ @bill.street.should == '123 Somewhere Dr'
64
+ @ship.street.should == '321 Anywhere Pl'
65
+ @bill.user.should == @found
66
+ @ship.user.should == @found
67
+ @bill.should be_a(Address)
68
+ @ship.should be_a(Address)
69
+ end
70
+
71
+ after :each do
72
+ User.destroy_all
73
+ end
74
+
75
+ after :all do
76
+ Object.send(:remove_const, :User)
77
+ Object.send(:remove_const, :Profile)
78
+ Object.send(:remove_const, :Address)
79
+ end
80
+
81
+ end
@@ -0,0 +1,54 @@
1
+ # Copyright 2010 Sean Cribbs, Sonian Inc., and Basho Technologies, Inc.
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__)
15
+
16
+ describe "Ripple Persistence" do
17
+ before :all do
18
+ switch_to_test_node
19
+ Object.module_eval do
20
+ class Widget
21
+ include Ripple::Document
22
+ property :name, String
23
+ property :size, Integer
24
+ end
25
+ end
26
+ end
27
+
28
+ before :each do
29
+ @widget = Widget.new
30
+ end
31
+
32
+ it "should save an object to the riak database" do
33
+ @widget.save
34
+ @found = Widget.find(@widget.key)
35
+ @found.should be_a(Widget)
36
+ end
37
+
38
+ it "should save attributes properly to riak" do
39
+ @widget.attributes = {:name => 'Sprocket', :size => 10}
40
+ @widget.save
41
+ @found = Widget.find(@widget.key)
42
+ @found.name.should == 'Sprocket'
43
+ @found.size.should == 10
44
+ end
45
+
46
+ after :each do
47
+ Widget.destroy_all
48
+ end
49
+
50
+ after :all do
51
+ Object.send(:remove_const, :Widget)
52
+ end
53
+
54
+ end
@@ -0,0 +1,124 @@
1
+ # Copyright 2010 Sean Cribbs, Sonian Inc., and Basho Technologies, Inc.
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__)
15
+
16
+ describe Ripple::Document::Associations::ManyEmbeddedProxy do
17
+ require 'support/models/user'
18
+ require 'support/models/address'
19
+ require 'support/models/note'
20
+
21
+ before :each do
22
+ @user = User.new
23
+ @address = Address.new
24
+ @addr = Address.new(:street => '123 Somewhere')
25
+ @note = Note.new
26
+ end
27
+
28
+ it "should not have children before any are set" do
29
+ @user.addresses.should == []
30
+ end
31
+
32
+ it "should be able to set and get its children" do
33
+ Address.stub!(:instantiate).and_return(@address)
34
+ @user.addresses = [@address]
35
+ @user.addresses.should == [@address]
36
+ end
37
+
38
+ it "should set the parent document on the children when assigning" do
39
+ @user.addresses = [@address]
40
+ @address._parent_document.should == @user
41
+ end
42
+
43
+ it "should return the assignment when assigning" do
44
+ rtn = @user.addresses = [@address]
45
+ rtn.should == [@address]
46
+ end
47
+
48
+ it "should set the parent document on the children when accessing" do
49
+ @user.addresses = [@address]
50
+ @user.addresses.first._parent_document.should == @user
51
+ end
52
+
53
+ it "should be able to replace its children with different children" do
54
+ @user.addresses = [@address]
55
+ @user.addresses.first.street.should be_blank
56
+ @user.addresses = [@addr]
57
+ @user.addresses.first.street.should == '123 Somewhere'
58
+ end
59
+
60
+ it "should be able to add to its children" do
61
+ Address.stub!(:instantiate).and_return(@address)
62
+ @user.addresses = [@address]
63
+ @user.addresses << @address
64
+ @user.addresses.should == [@address, @address]
65
+ end
66
+
67
+ it "should be able to chain calls to adding children" do
68
+ Address.stub!(:instantiate).and_return(@address)
69
+ @user.addresses = [@address]
70
+ @user.addresses << @address << @address << @address
71
+ @user.addresses.should == [@address, @address, @address, @address]
72
+ end
73
+
74
+ it "should set the parent document when adding to its children" do
75
+ @user.addresses << @address
76
+ @user.addresses.first._parent_document.should == @user
77
+ end
78
+
79
+ it "should be able to count its children" do
80
+ @user.addresses = [@address, @address]
81
+ @user.addresses.count.should == 2
82
+ end
83
+
84
+ it "should be able to build a new child" do
85
+ Address.stub!(:new).and_return(@address)
86
+ @user.addresses.build.should == @address
87
+ end
88
+
89
+ it "should assign a parent to the children created with instantiate_target" do
90
+ Address.stub!(:new).and_return(@address)
91
+ @address._parent_document.should be_nil
92
+ @user.addresses.build._parent_document.should == @user
93
+ end
94
+
95
+ it "should validate the children when saving the parent" do
96
+ @user.valid?.should be_true
97
+ @user.addresses << @address
98
+ @address.valid?.should be_false
99
+ @user.valid?.should be_false
100
+ end
101
+
102
+ it "should not save the root document when a child is invalid" do
103
+ @user.addresses << @address
104
+ @user.save.should be_false
105
+ end
106
+
107
+ it "should allow embedding documents in embedded documents" do
108
+ @user.addresses << @address
109
+ @address.notes << @note
110
+ @note._root_document.should == @user
111
+ @note._parent_document.should == @address
112
+ end
113
+
114
+ it "should allow assiging child documents as an array of hashes" do
115
+ @user.attributes = {'addresses' => [{'street' => '123 Somewhere'}]}
116
+ @user.addresses.first.street.should == '123 Somewhere'
117
+ end
118
+
119
+ it "should return an array from to_ary" do
120
+ Address.stub!(:instantiate).and_return(@address)
121
+ @user.addresses << @address
122
+ @user.addresses.to_ary.should == [@address]
123
+ end
124
+ end
@@ -0,0 +1,130 @@
1
+ # Copyright 2010 Sean Cribbs, Sonian Inc., and Basho Technologies, Inc.
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__)
15
+
16
+ describe Ripple::Document::Associations::OneEmbeddedProxy do
17
+ require 'support/models/family'
18
+ require 'support/models/user'
19
+ require 'support/models/address'
20
+
21
+ before :each do
22
+ @parent = Parent.new
23
+ @child = Child.new
24
+ @gchild = Grandchild.new
25
+ end
26
+
27
+ it "should not have a child before one is set" do
28
+ @parent.child.should be_nil
29
+ end
30
+
31
+ it "should be able to set and get its child" do
32
+ Child.stub!(:instantiate).and_return(@child)
33
+ @parent.child = @child
34
+ @parent.child.should == @child
35
+ end
36
+
37
+ it "should set the parent document on the child when assigning" do
38
+ @parent.child = @child
39
+ @child._parent_document.should == @parent
40
+ end
41
+
42
+ it "should return the assignment when assigning" do
43
+ rtn = @parent.child = @child
44
+ rtn.should == @child
45
+ end
46
+
47
+ it "should set the parent document on the child when accessing" do
48
+ @parent.child = @child
49
+ @parent.child._parent_document.should == @parent
50
+ end
51
+
52
+ it "should be able to replace its child with a different child" do
53
+ @son = Child.new(:name => 'Son')
54
+ @parent.child = @child
55
+ @parent.child.name.should be_blank
56
+ @parent.child = @son
57
+ @parent.child.name.should == 'Son'
58
+ end
59
+
60
+ it "should be able to build a new child" do
61
+ Child.stub!(:new).and_return(@child)
62
+ @parent.child.build.should == @child
63
+ end
64
+
65
+ it "should assign a parent to the child created with instantiate_target" do
66
+ Child.stub!(:new).and_return(@child)
67
+ @child._parent_document.should be_nil
68
+ @parent.child.build._parent_document.should == @parent
69
+ end
70
+
71
+ it "should validate the child when saving the parent" do
72
+ @parent.valid?.should be_true
73
+ @child.name = ''
74
+ @parent.child = @child
75
+ @child.valid?.should be_false
76
+ @parent.valid?.should be_false
77
+ end
78
+
79
+ it "should not save the root document when a child is invalid" do
80
+ @parent.child = @child
81
+ @parent.save.should be_false
82
+ end
83
+
84
+ it "should allow embedding documents in embedded documents" do
85
+ @parent.child = @child
86
+ @child.gchild = @gchild
87
+ @gchild._root_document.should == @parent
88
+ @gchild._parent_document.should == @child
89
+ end
90
+
91
+ describe "callbacks" do
92
+ before :each do
93
+ $pinger = mock("callback verifier")
94
+ end
95
+
96
+ it "should run callbacks for the child and documents" do
97
+ $pinger.should_receive(:ping).once
98
+ Child.before_validation { $pinger.ping }
99
+ @child = Child.new
100
+ @child.valid?
101
+ end
102
+
103
+ # this will work using parent and child classes, but only run by itself
104
+ # it also works using different classes, but only run in this file
105
+ # IDK why that is, but my Yakshaver 2000 just ran out of juice
106
+
107
+ # does this even matter? we call valid? all over the place and that
108
+ # will trigger the callback anyway.
109
+ # you probably shouldn't use validation callbacks and expect them to
110
+ # *only* run once
111
+
112
+ # it "should run callbacks for the parent and child and documents respectivly" do
113
+ # $pinger = mock("callback verifier")
114
+ # $pinger.should_receive(:ping).once
115
+ # $pinger.should_receive(:pong).once
116
+ # Child.before_validation { $pinger.ping }
117
+ # Parent.before_validation { $pinger.pong }
118
+ # @child = Child.new
119
+ # @parent = Parent.new
120
+ # @parent.child = @child
121
+ # @parent.valid?
122
+ # end
123
+
124
+ after :each do
125
+ Child.reset_callbacks(:validation)
126
+ Parent.reset_callbacks(:validation)
127
+ end
128
+ end
129
+
130
+ end
@@ -0,0 +1,78 @@
1
+ # Copyright 2010 Sean Cribbs, Sonian Inc., and Basho Technologies, Inc.
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__)
15
+
16
+ describe Ripple::Document::Associations::Proxy do
17
+ require 'support/associations/proxies'
18
+
19
+ before :each do
20
+ @owner = mock('owner')
21
+ @owner.stub!(:new?).and_return(false)
22
+ @association = mock('association')
23
+ @association.stub!(:options).and_return({:extend => []})
24
+
25
+ @proxy = FakeProxy.new(@owner, @association)
26
+ @nil_proxy = FakeNilProxy.new(@owner, @association)
27
+ @blank_proxy = FakeBlankProxy.new(@owner, @association)
28
+ end
29
+
30
+ it "should pretend to be the target class" do
31
+ @proxy.should be_kind_of(Array)
32
+ end
33
+
34
+ it "should set the target to nil when reset" do
35
+ @proxy.reset
36
+ @proxy.target.should be_nil
37
+ end
38
+
39
+ describe "delegation" do
40
+ it "should inspect the target" do
41
+ @proxy.inspect.should == "[1, 2]"
42
+ end
43
+
44
+ it "should respond to the same methods as the target" do
45
+ [:each, :size].each do |m|
46
+ @proxy.should respond_to(m)
47
+ end
48
+ @proxy.should_not respond_to(:gsub)
49
+ end
50
+
51
+ it "should send to the proxy if it responds to the method" do
52
+ @proxy.send(:reset)
53
+ @proxy.target.should be_nil
54
+ end
55
+
56
+ it "should send to the target if target responds to the method" do
57
+ @proxy.send(:size).should == 2
58
+ end
59
+
60
+ it "should send resulting in a method missing if neither the proxy nor the target respond to the method" do
61
+ lambda { @proxy.send(:gsub) }.should raise_error(NoMethodError)
62
+ end
63
+ end
64
+
65
+ describe "when target is nil" do
66
+ subject { @nil_proxy }
67
+ it { should be_nil }
68
+ it { should be_blank }
69
+ it { should_not be_present }
70
+ end
71
+
72
+ describe "when the target is blank" do
73
+ subject { @blank_proxy }
74
+ it { should_not be_nil }
75
+ it { should be_blank }
76
+ it { should_not be_present }
77
+ end
78
+ end