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,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ripple::EmbeddedDocument::Finders do
|
4
|
+
require 'support/models/address'
|
5
|
+
require 'support/models/favorite'
|
6
|
+
|
7
|
+
before :each do
|
8
|
+
@address = Address.new
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should instantiate a document" do
|
12
|
+
Address.stub!(:new).and_return(@address)
|
13
|
+
Address.instantiate('_type' => 'Address').should == @address
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should instantiate a class of _type if present in attrs" do
|
17
|
+
Favorite.instantiate('_type' => 'Address').class.should == Address
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should use self if being called from a class including Ripple::EmbeddedDocument and _type is not present" do
|
21
|
+
Address.instantiate({}).class.should == Address
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'initializes the document with no changes' do
|
25
|
+
a = Address.instantiate('_type' => 'Address', 'street' => 'Pine St')
|
26
|
+
a.should_not be_changed
|
27
|
+
a.changes.should be_empty
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ripple::EmbeddedDocument::Persistence do
|
4
|
+
require 'support/models/user'
|
5
|
+
require 'support/models/address'
|
6
|
+
|
7
|
+
before :each do
|
8
|
+
@root = User.new
|
9
|
+
@addr = Address.new(:street => "196 Broadway")
|
10
|
+
@addr._parent_document = @root
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should delegate new? to the root document" do
|
14
|
+
@root.should_receive(:new?).and_return(true)
|
15
|
+
@addr.should be_new
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should delegate save to the root document" do
|
19
|
+
@root.should_receive(:save).and_return(true)
|
20
|
+
@addr.save.should be_true
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should delegate save! to the root document" do
|
24
|
+
@root.should_receive(:save).and_return(true)
|
25
|
+
@addr.save!.should be_true
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should raise NoRootDocument when calling save without a root document" do
|
29
|
+
@addr._parent_document = nil
|
30
|
+
lambda { @addr.save }.should raise_error(Ripple::NoRootDocument)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should raise NoRootDocument when calling save! without a root document" do
|
34
|
+
@addr._parent_document = nil
|
35
|
+
lambda { @addr.save! }.should raise_error(Ripple::NoRootDocument)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should have a root document" do
|
39
|
+
@addr._root_document.should == @root
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should have a parent document" do
|
43
|
+
@addr._parent_document.should == @root
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should respond to new_record?" do
|
47
|
+
@addr.should respond_to(:new_record?)
|
48
|
+
@addr.should be_a_new_record
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should respond to persisted" do
|
52
|
+
@addr.should respond_to(:persisted?)
|
53
|
+
@addr.should_not be_persisted
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should properly create embedded attributes for persistence" do
|
57
|
+
@addr = Address.new
|
58
|
+
@root.addresses << @addr
|
59
|
+
@root.attributes_for_persistence.should == {'_type' => 'User', 'addresses' => [{'_type' => 'Address', 'street' => nil}]}
|
60
|
+
end
|
61
|
+
|
62
|
+
it "includes undefined properties in the attributes for persistence" do
|
63
|
+
addr = Address.new
|
64
|
+
addr['some_undefined_prop'] = 17
|
65
|
+
@root.addresses << addr
|
66
|
+
@root.attributes_for_persistence['addresses'].first.should include('some_undefined_prop' => 17)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should modify its attributes and save" do
|
70
|
+
@addr.should_receive(:save).and_return(true)
|
71
|
+
@addr.update_attributes(:street => "4 Folsom Ave")
|
72
|
+
@addr.street.should == "4 Folsom Ave"
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should update a single attribute and save without validations" do
|
76
|
+
@addr.should_receive(:save).with(:validate => false).and_return(true)
|
77
|
+
@addr.update_attribute(:street, "4 Folsom Ave")
|
78
|
+
@addr.street.should == "4 Folsom Ave"
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ripple::EmbeddedDocument do
|
4
|
+
require 'support/models/address'
|
5
|
+
require 'support/models/user'
|
6
|
+
|
7
|
+
it "should have a model name when included" do
|
8
|
+
Address.should respond_to(:model_name)
|
9
|
+
Address.model_name.should be_kind_of(ActiveModel::Name)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should be embeddable" do
|
13
|
+
Address.should be_embeddable
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "equality" do
|
17
|
+
let(:user_1) { User.new {|u| u.key = "u1"} }
|
18
|
+
let(:user_2) { User.new {|u| u.key = "u2"} }
|
19
|
+
let(:street_1) { '123 Somewhere St' }
|
20
|
+
let(:street_2) { '123 Somewhere Ave' }
|
21
|
+
let(:address_1) { Address.new(:street => street_1) }
|
22
|
+
let(:address_2) { Address.new(:street => street_1) }
|
23
|
+
|
24
|
+
before(:each) do
|
25
|
+
address_1._parent_document = user_1
|
26
|
+
address_2._parent_document = user_1
|
27
|
+
end
|
28
|
+
|
29
|
+
def should_be_equal
|
30
|
+
(address_1 == address_2).should be_true
|
31
|
+
address_1.eql?(address_2).should be_true
|
32
|
+
|
33
|
+
(address_2 == address_1).should be_true
|
34
|
+
address_2.eql?(address_1).should be_true
|
35
|
+
|
36
|
+
address_1.hash.should == address_2.hash
|
37
|
+
end
|
38
|
+
|
39
|
+
def should_not_be_equal(other_address = address_2)
|
40
|
+
(address_1 == other_address).should be_false
|
41
|
+
address_1.eql?(other_address).should be_false
|
42
|
+
|
43
|
+
(other_address == address_1).should be_false
|
44
|
+
address_1.eql?(other_address).should be_false
|
45
|
+
|
46
|
+
address_1.hash.should_not == other_address.hash
|
47
|
+
end
|
48
|
+
|
49
|
+
specify "two document are equal when they have the same classes, parents and attributes" do
|
50
|
+
should_be_equal
|
51
|
+
end
|
52
|
+
|
53
|
+
specify "two documents are not equal when the parents are different (even if the attributes and classes are the same)" do
|
54
|
+
address_2._parent_document = user_2
|
55
|
+
should_not_be_equal
|
56
|
+
end
|
57
|
+
|
58
|
+
specify "two documents are not equal when the attributes are different (even if the parents and classes are the same)" do
|
59
|
+
address_2.street = street_2
|
60
|
+
should_not_be_equal
|
61
|
+
end
|
62
|
+
|
63
|
+
specify "two documents are not equal when the classes are different (even if the parents and attributes are the same)" do
|
64
|
+
special_address = SpecialAddress.new(address_1.attributes)
|
65
|
+
special_address._parent_document = address_1._parent_document
|
66
|
+
|
67
|
+
should_not_be_equal(special_address)
|
68
|
+
end
|
69
|
+
|
70
|
+
specify "two documents are not equal when their embedded documents are not equal (even if they are identical otherwise)" do
|
71
|
+
address_1.notes << Note.new(:text => 'Bob lives here')
|
72
|
+
address_2.notes << Note.new(:text => 'Jill lives here')
|
73
|
+
|
74
|
+
should_not_be_equal
|
75
|
+
end
|
76
|
+
|
77
|
+
specify "two documents can be equal when their embedded doc objects are different instances but are equal" do
|
78
|
+
address_1.notes << Note.new(:text => 'Bob lives here')
|
79
|
+
address_2.notes << Note.new(:text => 'Bob lives here')
|
80
|
+
|
81
|
+
should_be_equal
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,217 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ripple::Document::Finders do
|
4
|
+
require 'support/models/box'
|
5
|
+
require 'support/models/cardboard_box'
|
6
|
+
|
7
|
+
before :each do
|
8
|
+
@backend = mock("Backend")
|
9
|
+
@client = Ripple.client
|
10
|
+
@client.stub!(:backend).and_return(@backend)
|
11
|
+
@bucket = Ripple.client.bucket("boxes")
|
12
|
+
@plain = Riak::RObject.new(@bucket, "square"){|o| o.content_type = "application/json"; o.raw_data = '{"shape":"square"}'}
|
13
|
+
@cb = Riak::RObject.new(@bucket, "rectangle"){|o| o.content_type = "application/json"; o.raw_data = '{"shape":"rectangle"}'}
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should return nil if no keys are passed to find" do
|
17
|
+
Box.find().should be_nil
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should return nil if no valid keys are passed to find" do
|
21
|
+
Box.find(nil).should be_nil
|
22
|
+
Box.find("").should be_nil
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should raise Ripple::DocumentNotFound if an empty array is passed to find!" do
|
26
|
+
lambda { Box.find!() }.should raise_error(Ripple::DocumentNotFound, "Couldn't find document without a key")
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "finding single documents" do
|
30
|
+
before do
|
31
|
+
@bucket.stub!(:get).with("square", {}).and_return(@plain)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should find a single document by key and assign its attributes" do
|
35
|
+
@bucket.should_receive(:get).with("square", {}).and_return(@plain)
|
36
|
+
box = Box.find("square")
|
37
|
+
box.should be_kind_of(Box)
|
38
|
+
box.shape.should == "square"
|
39
|
+
box.key.should == "square"
|
40
|
+
box.instance_variable_get(:@robject).should_not be_nil
|
41
|
+
box.should_not be_new_record
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should find the first document using the first key with the bucket's keys" do
|
45
|
+
box = Box.new
|
46
|
+
keys = ['some_boxes_key']
|
47
|
+
Box.stub!(:find).and_return(box)
|
48
|
+
@bucket.stub!(:keys).and_return(keys)
|
49
|
+
@bucket.should_receive(:keys)
|
50
|
+
keys.should_receive(:first)
|
51
|
+
Box.first.should == box
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should use find! when using first!" do
|
55
|
+
box = Box.new
|
56
|
+
Box.stub!(:find!).and_return(box)
|
57
|
+
@bucket.stub!(:keys).and_return(['key'])
|
58
|
+
Box.first!.should == box
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should not raise an exception when finding an existing document with find!" do
|
62
|
+
lambda { Box.find!("square") }.should_not raise_error(Ripple::DocumentNotFound)
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should put properties we don't know about into the attributes" do
|
66
|
+
@plain.raw_data = '{"non_existent_property":"some_value"}'
|
67
|
+
box = Box.find("square")
|
68
|
+
box[:non_existent_property].should == "some_value"
|
69
|
+
box.should_not respond_to(:non_existent_property)
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should return the document when calling find!" do
|
73
|
+
box = Box.find!("square")
|
74
|
+
box.should be_kind_of(Box)
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should return nil when no object exists at that key" do
|
78
|
+
@bucket.should_receive(:get).with("square", {}).and_raise(Riak::HTTPFailedRequest.new(:get, 200, 404, {}, "404 not found"))
|
79
|
+
box = Box.find("square")
|
80
|
+
box.should be_nil
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should raise DocumentNotFound when using find! if no object exists at that key" do
|
84
|
+
@bucket.should_receive(:get).with("square", {}).and_raise(Riak::HTTPFailedRequest.new(:get, 200, 404, {}, "404 not found"))
|
85
|
+
lambda { Box.find!("square") }.should raise_error(Ripple::DocumentNotFound, "Couldn't find document with key: square")
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should re-raise the failed request exception if not a 404" do
|
89
|
+
@bucket.should_receive(:get).with("square", {}).and_raise(Riak::HTTPFailedRequest.new(:get, 200, 500, {}, "500 internal server error"))
|
90
|
+
lambda { Box.find("square") }.should raise_error(Riak::FailedRequest)
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should handle a key with a nil value" do
|
94
|
+
@plain.raw_data = nil
|
95
|
+
@plain.data = nil
|
96
|
+
box = Box.find("square")
|
97
|
+
box.should be_kind_of(Box)
|
98
|
+
box.key.should == "square"
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'initializes the document with no changed attributes' do
|
102
|
+
box = Box.find("square")
|
103
|
+
box.should_not be_changed
|
104
|
+
box.changes.should be_empty
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe "finding multiple documents when given a splat of keys" do
|
109
|
+
it "should find multiple documents by the keys" do
|
110
|
+
@bucket.should_receive(:get).with("square", {}).and_return(@plain)
|
111
|
+
@bucket.should_receive(:get).with("rectangle", {}).and_return(@cb)
|
112
|
+
boxes = Box.find("square", "rectangle")
|
113
|
+
boxes.should have(2).items
|
114
|
+
boxes.first.shape.should == "square"
|
115
|
+
boxes.last.shape.should == "rectangle"
|
116
|
+
end
|
117
|
+
|
118
|
+
describe "when using find with missing keys" do
|
119
|
+
before :each do
|
120
|
+
@bucket.should_receive(:get).with("square", {}).and_return(@plain)
|
121
|
+
@bucket.should_receive(:get).with("rectangle", {}).and_raise(Riak::HTTPFailedRequest.new(:get, 200, 404, {}, "404 not found"))
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should return nil for documents that no longer exist" do
|
125
|
+
boxes = Box.find("square", "rectangle")
|
126
|
+
boxes.should have(2).items
|
127
|
+
boxes.first.shape.should == "square"
|
128
|
+
boxes.last.should be_nil
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should raise Ripple::DocumentNotFound when calling find! if some of the documents do not exist" do
|
132
|
+
lambda { Box.find!("square", "rectangle") }.should raise_error(Ripple::DocumentNotFound, "Couldn't find documents with keys: rectangle")
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe "finding multiple documents when given an array" do
|
138
|
+
it "should find multiple documents by the keys" do
|
139
|
+
@bucket.should_receive(:get).with("square", {}).and_return(@plain)
|
140
|
+
@bucket.should_receive(:get).with("rectangle", {}).and_return(@cb)
|
141
|
+
boxes = Box.find(["square", "rectangle"])
|
142
|
+
boxes.should have(2).items
|
143
|
+
boxes.first.shape.should == "square"
|
144
|
+
boxes.last.shape.should == "rectangle"
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should return an array of docs when given an array of one key" do
|
148
|
+
@bucket.should_receive(:get).with("square", {}).and_return(@plain)
|
149
|
+
boxes = Box.find(["square"])
|
150
|
+
boxes.should have(1).items
|
151
|
+
boxes.first.shape.should == "square"
|
152
|
+
end
|
153
|
+
|
154
|
+
it "should return an empty array when given an empty array" do
|
155
|
+
Box.find([ ]).should == []
|
156
|
+
end
|
157
|
+
|
158
|
+
describe "when using find with missing keys" do
|
159
|
+
before :each do
|
160
|
+
@bucket.should_receive(:get).with("square", {}).and_return(@plain)
|
161
|
+
@bucket.should_receive(:get).with("rectangle", {}).and_raise(Riak::HTTPFailedRequest.new(:get, 200, 404, {}, "404 not found"))
|
162
|
+
end
|
163
|
+
|
164
|
+
it "should return nil for documents that no longer exist" do
|
165
|
+
boxes = Box.find(["square", "rectangle"])
|
166
|
+
boxes.should have(2).items
|
167
|
+
boxes.first.shape.should == "square"
|
168
|
+
boxes.last.should be_nil
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
describe "listings all documents in the bucket" do
|
174
|
+
it "should load all objects in the bucket" do
|
175
|
+
@bucket.should_receive(:keys).and_return(["square", "rectangle"])
|
176
|
+
@bucket.should_receive(:get).with("square", {}).and_return(@plain)
|
177
|
+
@bucket.should_receive(:get).with("rectangle", {}).and_return(@cb)
|
178
|
+
boxes = Box.list
|
179
|
+
boxes.should have(2).items
|
180
|
+
boxes.first.shape.should == "square"
|
181
|
+
boxes.last.shape.should == "rectangle"
|
182
|
+
end
|
183
|
+
|
184
|
+
it "should exclude objects that are not found" do
|
185
|
+
@bucket.should_receive(:keys).and_return(["square", "rectangle"])
|
186
|
+
@bucket.should_receive(:get).with("square", {}).and_return(@plain)
|
187
|
+
@bucket.should_receive(:get).with("rectangle", {}).and_raise(Riak::HTTPFailedRequest.new(:get, 200, 404, {}, "404 not found"))
|
188
|
+
boxes = Box.list
|
189
|
+
boxes.should have(1).item
|
190
|
+
boxes.first.shape.should == "square"
|
191
|
+
end
|
192
|
+
|
193
|
+
it "should yield found objects to the passed block, excluding missing objects, and return an empty array" do
|
194
|
+
@bucket.should_receive(:keys).and_yield(["square"]).and_yield(["rectangle"])
|
195
|
+
@bucket.should_receive(:get).with("square", {}).and_return(@plain)
|
196
|
+
@bucket.should_receive(:get).with("rectangle", {}).and_raise(Riak::HTTPFailedRequest.new(:get, 200, 404, {}, "404 not found"))
|
197
|
+
@block = mock()
|
198
|
+
@block.should_receive(:ping).once
|
199
|
+
Box.list do |box|
|
200
|
+
@block.ping
|
201
|
+
["square", "rectangle"].should include(box.shape)
|
202
|
+
end.should == []
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
describe "single-bucket inheritance" do
|
207
|
+
it "should instantiate as the proper type if defined in the document" do
|
208
|
+
@cb.raw_data = '{"shape":"rectangle", "_type":"CardboardBox"}'
|
209
|
+
@bucket.should_receive(:get).with("square", {}).and_return(@plain)
|
210
|
+
@bucket.should_receive(:get).with("rectangle", {}).and_return(@cb)
|
211
|
+
boxes = Box.find("square", "rectangle")
|
212
|
+
boxes.should have(2).items
|
213
|
+
boxes.first.class.should == Box
|
214
|
+
boxes.last.should be_kind_of(CardboardBox)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ripple::Inspection do
|
4
|
+
require 'support/models/box'
|
5
|
+
require 'support/models/address'
|
6
|
+
|
7
|
+
shared_examples_for 'an inspected document' do |method|
|
8
|
+
|
9
|
+
it "should include the class name in the inspect string" do
|
10
|
+
@box.send(method).should be_starts_with("<Box")
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should include the key in the #{method} string for documents" do
|
14
|
+
@box.key = "square"
|
15
|
+
@box.send(method).should be_starts_with("<Box:square")
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should indicate a new document when no key is specified" do
|
19
|
+
@box.send(method).should be_starts_with("<Box:[new]")
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should not display a key for embedded documents" do
|
23
|
+
@address.send(method).should_not include("[new]")
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
before :each do
|
29
|
+
@box = Box.new
|
30
|
+
@address = Address.new
|
31
|
+
end
|
32
|
+
|
33
|
+
describe '#inspect' do
|
34
|
+
|
35
|
+
it_should_behave_like 'an inspected document', :inspect
|
36
|
+
|
37
|
+
it "should enumerate the document's properties and their values" do
|
38
|
+
@box.shape = "square"
|
39
|
+
@box.inspect.should include("shape=\"square\"")
|
40
|
+
@box.inspect.should include("created_at=")
|
41
|
+
@box.inspect.should include("updated_at=")
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
describe '#to_s' do
|
47
|
+
|
48
|
+
it_should_behave_like 'an inspected document', :to_s
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|