seomoz-ripple 1.0.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +20 -0
- data/Guardfile +15 -0
- data/Rakefile +88 -0
- data/lib/rails/generators/ripple/configuration/configuration_generator.rb +13 -0
- data/lib/rails/generators/ripple/configuration/templates/ripple.yml +24 -0
- data/lib/rails/generators/ripple/js/js_generator.rb +13 -0
- data/lib/rails/generators/ripple/js/templates/js/contrib.js +63 -0
- data/lib/rails/generators/ripple/js/templates/js/iso8601.js +76 -0
- data/lib/rails/generators/ripple/js/templates/js/ripple.js +132 -0
- data/lib/rails/generators/ripple/model/model_generator.rb +20 -0
- data/lib/rails/generators/ripple/model/templates/model.rb +10 -0
- data/lib/rails/generators/ripple/observer/observer_generator.rb +16 -0
- data/lib/rails/generators/ripple/observer/templates/observer.rb +4 -0
- data/lib/rails/generators/ripple/test/templates/test_server.rb +46 -0
- data/lib/rails/generators/ripple/test/test_generator.rb +39 -0
- data/lib/rails/generators/ripple_generator.rb +78 -0
- data/lib/ripple.rb +79 -0
- data/lib/ripple/associations.rb +356 -0
- data/lib/ripple/associations/embedded.rb +35 -0
- data/lib/ripple/associations/instantiators.rb +26 -0
- data/lib/ripple/associations/linked.rb +65 -0
- data/lib/ripple/associations/many.rb +38 -0
- data/lib/ripple/associations/many_embedded_proxy.rb +38 -0
- data/lib/ripple/associations/many_linked_proxy.rb +66 -0
- 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 +20 -0
- data/lib/ripple/associations/one_embedded_proxy.rb +35 -0
- data/lib/ripple/associations/one_key_proxy.rb +58 -0
- data/lib/ripple/associations/one_linked_proxy.rb +22 -0
- data/lib/ripple/associations/one_stored_key_proxy.rb +43 -0
- data/lib/ripple/associations/proxy.rb +118 -0
- data/lib/ripple/attribute_methods.rb +118 -0
- data/lib/ripple/attribute_methods/dirty.rb +50 -0
- data/lib/ripple/attribute_methods/query.rb +34 -0
- data/lib/ripple/attribute_methods/read.rb +26 -0
- data/lib/ripple/attribute_methods/write.rb +25 -0
- data/lib/ripple/callbacks.rb +74 -0
- 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 +28 -0
- data/lib/ripple/core_ext.rb +2 -0
- data/lib/ripple/core_ext/casting.rb +148 -0
- data/lib/ripple/core_ext/object.rb +8 -0
- data/lib/ripple/document.rb +104 -0
- data/lib/ripple/document/bucket_access.rb +25 -0
- data/lib/ripple/document/finders.rb +131 -0
- data/lib/ripple/document/key.rb +43 -0
- data/lib/ripple/document/link.rb +30 -0
- data/lib/ripple/document/persistence.rb +115 -0
- data/lib/ripple/embedded_document.rb +64 -0
- data/lib/ripple/embedded_document/around_callbacks.rb +18 -0
- data/lib/ripple/embedded_document/finders.rb +26 -0
- data/lib/ripple/embedded_document/persistence.rb +77 -0
- data/lib/ripple/i18n.rb +2 -0
- data/lib/ripple/inspection.rb +32 -0
- data/lib/ripple/locale/en.yml +21 -0
- data/lib/ripple/nested_attributes.rb +265 -0
- data/lib/ripple/observable.rb +28 -0
- data/lib/ripple/properties.rb +73 -0
- data/lib/ripple/property_type_mismatch.rb +12 -0
- data/lib/ripple/railtie.rb +13 -0
- data/lib/ripple/serialization.rb +84 -0
- data/lib/ripple/timestamps.rb +27 -0
- data/lib/ripple/translation.rb +14 -0
- data/lib/ripple/validations.rb +67 -0
- data/lib/ripple/validations/associated_validator.rb +43 -0
- data/ripple.gemspec +46 -0
- data/seomoz-ripple.gemspec +46 -0
- data/spec/fixtures/config.yml +8 -0
- data/spec/integration/ripple/associations_spec.rb +220 -0
- data/spec/integration/ripple/conflict_resolution_spec.rb +293 -0
- data/spec/integration/ripple/nested_attributes_spec.rb +264 -0
- data/spec/integration/ripple/persistence_spec.rb +57 -0
- data/spec/integration/ripple/search_associations_spec.rb +42 -0
- data/spec/ripple/associations/many_embedded_proxy_spec.rb +122 -0
- data/spec/ripple/associations/many_linked_proxy_spec.rb +191 -0
- 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 +125 -0
- data/spec/ripple/associations/one_key_proxy_spec.rb +82 -0
- data/spec/ripple/associations/one_linked_proxy_spec.rb +91 -0
- data/spec/ripple/associations/one_stored_key_proxy_spec.rb +72 -0
- data/spec/ripple/associations/proxy_spec.rb +84 -0
- data/spec/ripple/associations_spec.rb +129 -0
- data/spec/ripple/attribute_methods/dirty_spec.rb +80 -0
- data/spec/ripple/attribute_methods_spec.rb +230 -0
- data/spec/ripple/bucket_access_spec.rb +25 -0
- data/spec/ripple/callbacks_spec.rb +176 -0
- data/spec/ripple/conflict/resolver_spec.rb +42 -0
- data/spec/ripple/conversion_spec.rb +22 -0
- data/spec/ripple/core_ext_spec.rb +103 -0
- data/spec/ripple/document/link_spec.rb +67 -0
- data/spec/ripple/document_spec.rb +96 -0
- data/spec/ripple/embedded_document/finders_spec.rb +29 -0
- data/spec/ripple/embedded_document/persistence_spec.rb +80 -0
- data/spec/ripple/embedded_document_spec.rb +84 -0
- data/spec/ripple/finders_spec.rb +217 -0
- data/spec/ripple/inspection_spec.rb +51 -0
- data/spec/ripple/key_spec.rb +30 -0
- data/spec/ripple/observable_spec.rb +121 -0
- data/spec/ripple/persistence_spec.rb +326 -0
- data/spec/ripple/properties_spec.rb +262 -0
- data/spec/ripple/ripple_spec.rb +71 -0
- data/spec/ripple/serialization_spec.rb +51 -0
- data/spec/ripple/timestamps_spec.rb +76 -0
- data/spec/ripple/validations/associated_validator_spec.rb +77 -0
- data/spec/ripple/validations_spec.rb +104 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/support/associations.rb +1 -0
- data/spec/support/associations/proxies.rb +17 -0
- data/spec/support/integration_setup.rb +11 -0
- data/spec/support/mocks.rb +4 -0
- data/spec/support/models.rb +4 -0
- data/spec/support/models/address.rb +12 -0
- data/spec/support/models/box.rb +13 -0
- data/spec/support/models/car.rb +16 -0
- data/spec/support/models/cardboard_box.rb +3 -0
- data/spec/support/models/clock.rb +12 -0
- data/spec/support/models/clock_observer.rb +3 -0
- data/spec/support/models/company.rb +23 -0
- data/spec/support/models/customer.rb +4 -0
- data/spec/support/models/driver.rb +6 -0
- data/spec/support/models/email.rb +4 -0
- data/spec/support/models/engine.rb +5 -0
- data/spec/support/models/family.rb +16 -0
- data/spec/support/models/favorite.rb +4 -0
- data/spec/support/models/invoice.rb +7 -0
- data/spec/support/models/late_invoice.rb +3 -0
- data/spec/support/models/ninja.rb +9 -0
- data/spec/support/models/note.rb +5 -0
- data/spec/support/models/page.rb +4 -0
- data/spec/support/models/paid_invoice.rb +4 -0
- data/spec/support/models/passenger.rb +6 -0
- data/spec/support/models/profile.rb +10 -0
- data/spec/support/models/seat.rb +5 -0
- data/spec/support/models/subscription.rb +27 -0
- data/spec/support/models/tasks.rb +14 -0
- data/spec/support/models/team.rb +11 -0
- data/spec/support/models/transactions.rb +17 -0
- data/spec/support/models/tree.rb +4 -0
- data/spec/support/models/user.rb +10 -0
- data/spec/support/models/wheel.rb +6 -0
- data/spec/support/models/widget.rb +22 -0
- data/spec/support/test_server.rb +18 -0
- data/spec/support/test_server.yml.example +2 -0
- metadata +362 -0
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ripple::Associations::OneEmbeddedProxy do
|
4
|
+
require 'support/models/family'
|
5
|
+
require 'support/models/user'
|
6
|
+
require 'support/models/address'
|
7
|
+
|
8
|
+
before :each do
|
9
|
+
@parent = Parent.new
|
10
|
+
@child = Child.new
|
11
|
+
@gchild = Grandchild.new
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should not have a child before one is set" do
|
15
|
+
@parent.child.should be_nil
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should raise NoMethodError when an undefined method is called on the unset child" do
|
19
|
+
expect { @parent.child.some_undefined_method }.to raise_error(NoMethodError)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should be able to set and get its child" do
|
23
|
+
@parent.child = @child
|
24
|
+
@parent.child.should equal(@child)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should set the parent document on the child when assigning" do
|
28
|
+
@parent.child = @child
|
29
|
+
@child._parent_document.should == @parent
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should return the assignment when assigning" do
|
33
|
+
rtn = @parent.child = @child
|
34
|
+
rtn.should == @child
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should set the parent document on the child when accessing" do
|
38
|
+
@parent.child = @child
|
39
|
+
@parent.child._parent_document.should == @parent
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should be able to replace its child with a different child" do
|
43
|
+
@son = Child.new(:name => 'Son')
|
44
|
+
@parent.child = @child
|
45
|
+
@parent.child.name.should be_blank
|
46
|
+
@parent.child = @son
|
47
|
+
@parent.child.name.should == 'Son'
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should be able to build a new child" do
|
51
|
+
Child.stub!(:new).and_return(@child)
|
52
|
+
@parent.child.build.should == @child
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should assign a parent to the child created with instantiate_target" do
|
56
|
+
Child.stub!(:new).and_return(@child)
|
57
|
+
@child._parent_document.should be_nil
|
58
|
+
@parent.child.build._parent_document.should == @parent
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should validate the child when saving the parent" do
|
62
|
+
@parent.valid?.should be_true
|
63
|
+
@child.name = ''
|
64
|
+
@parent.child = @child
|
65
|
+
@child.valid?.should be_false
|
66
|
+
@parent.valid?.should be_false
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should not save the root document when a child is invalid" do
|
70
|
+
@parent.child = @child
|
71
|
+
@parent.save.should be_false
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should allow embedding documents in embedded documents" do
|
75
|
+
@parent.child = @child
|
76
|
+
@child.gchild = @gchild
|
77
|
+
@gchild._root_document.should == @parent
|
78
|
+
@gchild._parent_document.should == @child
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should refuse assigning a document of the wrong type" do
|
82
|
+
lambda { @parent.child = @gchild }.should raise_error
|
83
|
+
lambda { @child.gchild = [] }.should raise_error
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "callbacks" do
|
87
|
+
before :each do
|
88
|
+
$pinger = mock("callback verifier")
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should run callbacks for the child and documents" do
|
92
|
+
$pinger.should_receive(:ping).once
|
93
|
+
Child.before_validation { $pinger.ping }
|
94
|
+
@child = Child.new
|
95
|
+
@child.valid?
|
96
|
+
end
|
97
|
+
|
98
|
+
# this will work using parent and child classes, but only run by itself
|
99
|
+
# it also works using different classes, but only run in this file
|
100
|
+
# IDK why that is, but my Yakshaver 2000 just ran out of juice
|
101
|
+
|
102
|
+
# does this even matter? we call valid? all over the place and that
|
103
|
+
# will trigger the callback anyway.
|
104
|
+
# you probably shouldn't use validation callbacks and expect them to
|
105
|
+
# *only* run once
|
106
|
+
|
107
|
+
# it "should run callbacks for the parent and child and documents respectivly" do
|
108
|
+
# $pinger = mock("callback verifier")
|
109
|
+
# $pinger.should_receive(:ping).once
|
110
|
+
# $pinger.should_receive(:pong).once
|
111
|
+
# Child.before_validation { $pinger.ping }
|
112
|
+
# Parent.before_validation { $pinger.pong }
|
113
|
+
# @child = Child.new
|
114
|
+
# @parent = Parent.new
|
115
|
+
# @parent.child = @child
|
116
|
+
# @parent.valid?
|
117
|
+
# end
|
118
|
+
|
119
|
+
after :each do
|
120
|
+
Child.reset_callbacks(:validation)
|
121
|
+
Parent.reset_callbacks(:validation)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ripple::Associations::OneKeyProxy do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
@user = User.new
|
7
|
+
@profile = Profile.new(:color => 'blue')
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "User with a key corresponded profile" do
|
11
|
+
it "should not have a profile before it is set" do
|
12
|
+
@user.profile.should be_nil
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should be able to get and set its profile" do
|
16
|
+
@user.profile = @profile
|
17
|
+
@user.profile.should eq(@profile)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should return the assignment when assigning" do
|
21
|
+
rtn = @user.profile = @profile
|
22
|
+
rtn.should eq(@profile)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should be able to replace its profile with a new one" do
|
26
|
+
@user.profile = @profile
|
27
|
+
@user.profile = Profile.new(:color => 'red')
|
28
|
+
@user.profile.color.should eq('red')
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should be able to build a new profile" do
|
32
|
+
Profile.stub(:new).and_return(@profile)
|
33
|
+
@user.profile.build.should eq(@profile)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should assign its key to the associated profile when assigning" do
|
37
|
+
@user.key = "foo"
|
38
|
+
@user.profile = @profile
|
39
|
+
@profile.key.should eq("foo")
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should assign its key to the built profile" do
|
43
|
+
@user.key = "foo"
|
44
|
+
@user.profile.build.key.should eq("foo")
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should update the key on the profile when updating it on the user" do
|
48
|
+
@user.profile = @profile
|
49
|
+
@user.key = "foo"
|
50
|
+
@profile.key.should eq("foo")
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should not update the key of a previous profile" do
|
54
|
+
@profile2 = Profile.new
|
55
|
+
@user.profile = @profile
|
56
|
+
@user.profile = @profile2
|
57
|
+
@user.key = "foo"
|
58
|
+
@profile.key.should_not eq("foo")
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should not infinitely loop when assigning a user to the profile" do
|
62
|
+
@user2 = User.new
|
63
|
+
@user.profile = @profile
|
64
|
+
@profile.user = @user2
|
65
|
+
@profile.key = "foo"
|
66
|
+
@user2.key.should eq("foo")
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should update the user's key when being updated on the profile" do
|
70
|
+
@user.profile = @profile
|
71
|
+
@profile.key = "foo"
|
72
|
+
@user.key.should eq("foo")
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should work properly with custom key methods" do
|
76
|
+
@user = Ninja.new(:name => 'Naruto')
|
77
|
+
@user.profile = @profile
|
78
|
+
@profile.key.should eq("ninja-naruto")
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ripple::Associations::OneLinkedProxy do
|
4
|
+
require 'support/models/tasks'
|
5
|
+
require 'support/models/family'
|
6
|
+
|
7
|
+
before :each do
|
8
|
+
@person = Person.new {|p| p.key = "riak-user" }
|
9
|
+
@profile = Profile.new {|t| t.key = "one" }
|
10
|
+
@other_profile = Profile.new {|t| t.key = "two" }
|
11
|
+
[@person, @profile, @other_profile].each do |doc|
|
12
|
+
doc.stub!(:new?).and_return(false)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should be blank before the associated document is set" do
|
17
|
+
@person.profile.should_not be_present
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should accept a single document" do
|
21
|
+
lambda { @person.profile = @profile }.should_not raise_error
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should set the link on the RObject when assigning" do
|
25
|
+
@person.profile = @profile
|
26
|
+
@person.robject.links.should include(@profile.to_link("profile"))
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should return the assigned document when assigning" do
|
30
|
+
ret = (@person.profile = @profile)
|
31
|
+
ret.should == @profile
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should link-walk to the associated document when accessing" do
|
35
|
+
@person.robject.links << @profile.robject.to_link("profile")
|
36
|
+
@person.robject.should_receive(:walk).with(Riak::WalkSpec.new(:bucket => "profiles", :tag => "profile")).and_return([[@profile.robject]])
|
37
|
+
@person.profile.should be_present
|
38
|
+
end
|
39
|
+
|
40
|
+
it "handles conflict appropriately by selecting the linked-walk robject that matches the link" do
|
41
|
+
@person.robject.links << @profile.robject.to_link("profile")
|
42
|
+
@person.robject.
|
43
|
+
should_receive(:walk).
|
44
|
+
with(Riak::WalkSpec.new(:bucket => "profiles", :tag => "profile")).
|
45
|
+
and_return([[@other_profile.robject, @profile.robject]])
|
46
|
+
|
47
|
+
@person.profile.should == @profile
|
48
|
+
end
|
49
|
+
|
50
|
+
it "allows the links to be replaced directly" do
|
51
|
+
@person.profile = @profile
|
52
|
+
@person.profile.__send__(:should_receive, :reset)
|
53
|
+
@person.profile.__send__(:links).should == [@profile.robject.to_link("profile")]
|
54
|
+
@person.profile.replace_links(@other_profile.robject.to_link("profile"))
|
55
|
+
@person.profile.__send__(:links).should == [@other_profile.robject.to_link("profile")]
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should return nil immediately if the association link is missing" do
|
59
|
+
@person.robject.links.should be_empty
|
60
|
+
@person.profile.should be_nil
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should replace associated document with a new one" do
|
64
|
+
@person.profile = @profile
|
65
|
+
@person.profile = @other_profile
|
66
|
+
@person.profile.should == @other_profile
|
67
|
+
end
|
68
|
+
|
69
|
+
it "replaces the associated document with the target of the proxy" do
|
70
|
+
@other_person = Person.new {|p| p.key = "another-riak-user" }
|
71
|
+
@other_person.profile = @other_profile
|
72
|
+
|
73
|
+
@person.profile = @other_person.profile
|
74
|
+
@person.profile.should == @other_profile
|
75
|
+
end
|
76
|
+
|
77
|
+
it "refuses assigning a proxy if its target is the wrong type" do
|
78
|
+
parent = Parent.new
|
79
|
+
parent.child = Child.new
|
80
|
+
|
81
|
+
lambda { @person.profile = parent.child }.should raise_error
|
82
|
+
end
|
83
|
+
|
84
|
+
# it "should be able to build a new associated document" do
|
85
|
+
# @person.profile.build
|
86
|
+
# end
|
87
|
+
|
88
|
+
it "should refuse assigning a document of the wrong type" do
|
89
|
+
lambda { @person.profile = @person }.should raise_error
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ripple::Associations::OneStoredKeyProxy do
|
4
|
+
require 'support/models/transactions'
|
5
|
+
require 'support/models/family'
|
6
|
+
|
7
|
+
before :each do
|
8
|
+
@account = Account.new {|e| e.key = "accounty" }
|
9
|
+
@other_account = Account.new{|e| e.key = "ickycount" }
|
10
|
+
@transaction = Transaction.new{|e| e.key = "transacty" }
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should be blank before the associated document is set" do
|
14
|
+
@transaction.account.should_not be_present
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should accept a single document" do
|
18
|
+
lambda { @transaction.account = @account }.should_not raise_error
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should set the key when assigning" do
|
22
|
+
@transaction.account = @account
|
23
|
+
@transaction.account_key.should == "accounty"
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should return the assigned document when assigning" do
|
27
|
+
ret = (@transaction.account = @account)
|
28
|
+
ret.should == @account
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should find the associated document when accessing" do
|
32
|
+
@transaction.account_key = "accounty"
|
33
|
+
Account.should_receive(:find).with("accounty").and_return(@account)
|
34
|
+
@transaction.account.should be_present
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should return nil immediately if the association link is missing" do
|
38
|
+
@transaction.account_key.should be_nil
|
39
|
+
@transaction.account.should be_nil
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should replace associated document with a new one" do
|
43
|
+
@transaction.account = @account
|
44
|
+
@transaction.account = @other_account
|
45
|
+
@transaction.account.should == @other_account
|
46
|
+
@transaction.account_key.should == "ickycount"
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should replace the associated document with the target of the proxy" do
|
50
|
+
other_transaction = Transaction.new {|e| e.key = "ickytrans" }
|
51
|
+
other_transaction.account = @other_account
|
52
|
+
|
53
|
+
@transaction.account = other_transaction.account
|
54
|
+
@transaction.account.should == @other_account
|
55
|
+
end
|
56
|
+
|
57
|
+
it "refuses assigning a proxy if its target is the wrong type" do
|
58
|
+
parent = Parent.new{|e| e.child = Child.new}
|
59
|
+
lambda { @transaction.account = parent.child }.should raise_error
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should refuse assigning a document of the wrong type" do
|
63
|
+
lambda { @transaction.account = @transaction }.should raise_error
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should nil out the association if nil is assigned" do
|
67
|
+
@transaction.account = @account
|
68
|
+
@transaction.account = nil
|
69
|
+
@transaction.account.should be_nil
|
70
|
+
@transaction.account_key.should be_nil
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ripple::Associations::Proxy do
|
4
|
+
require 'support/associations/proxies'
|
5
|
+
|
6
|
+
before :each do
|
7
|
+
@owner = mock('owner')
|
8
|
+
@owner.stub!(:new?).and_return(false)
|
9
|
+
@association = mock('association')
|
10
|
+
@association.stub!(:options).and_return({:extend => []})
|
11
|
+
|
12
|
+
@proxy = FakeProxy.new(@owner, @association)
|
13
|
+
@nil_proxy = FakeNilProxy.new(@owner, @association)
|
14
|
+
@blank_proxy = FakeBlankProxy.new(@owner, @association)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should pretend to be the target class" do
|
18
|
+
@proxy.should be_kind_of(Array)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should set the target to nil when reset" do
|
22
|
+
@proxy.reset
|
23
|
+
@proxy.target.should be_nil
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "delegation" do
|
27
|
+
it "should inspect the target" do
|
28
|
+
@proxy.inspect.should == "[1, 2]"
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should respond to the same methods as the target" do
|
32
|
+
[:each, :size].each do |m|
|
33
|
+
@proxy.should respond_to(m)
|
34
|
+
end
|
35
|
+
@proxy.should_not respond_to(:gsub)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should send to the proxy if it responds to the method" do
|
39
|
+
@proxy.send(:reset)
|
40
|
+
@proxy.target.should be_nil
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should send to the target if target responds to the method" do
|
44
|
+
@proxy.send(:size).should == 2
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should send resulting in a method missing if neither the proxy nor the target respond to the method" do
|
48
|
+
lambda { @proxy.send(:explode) }.should raise_error(NoMethodError)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "when target is nil" do
|
53
|
+
subject { @nil_proxy }
|
54
|
+
it { should be_nil }
|
55
|
+
it { should be_blank }
|
56
|
+
it { should_not be_present }
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "when the target is blank" do
|
60
|
+
subject { @blank_proxy }
|
61
|
+
it { should_not be_nil }
|
62
|
+
it { should be_blank }
|
63
|
+
it { should_not be_present }
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "#has_changed_documents?" do
|
67
|
+
before(:each) { @proxy.respond_to?(:loaded_documents).should be_true }
|
68
|
+
|
69
|
+
it "returns true if any of the loaded documents return true from #changed?" do
|
70
|
+
@proxy.stub(:loaded_documents => [stub(:changed? => false), stub(:changed? => true)])
|
71
|
+
@proxy.has_changed_documents?.should be_true
|
72
|
+
end
|
73
|
+
|
74
|
+
it "returns false if none of the loaded documents return true from #changed?" do
|
75
|
+
@proxy.stub(:loaded_documents => [stub(:changed? => false), stub(:changed? => false)])
|
76
|
+
@proxy.has_changed_documents?.should be_false
|
77
|
+
end
|
78
|
+
|
79
|
+
it "returns false if it has no loaded documents" do
|
80
|
+
@proxy.stub(:loaded_documents => [])
|
81
|
+
@proxy.has_changed_documents?.should be_false
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|