spec/ripple/persistence_spec.rb in ripple-0.9.5 vs spec/ripple/persistence_spec.rb in ripple-1.0.0.beta
- old
+ new
@@ -1,31 +1,28 @@
-# Copyright 2010 Sean Cribbs, Sonian Inc., and Basho Technologies, Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-require File.expand_path("../../spec_helper", __FILE__)
+require 'spec_helper'
describe Ripple::Document::Persistence do
- require 'support/models/widget'
+ # require 'support/models/widget'
before :each do
@backend = mock("Backend")
@client = Ripple.client
@client.stub!(:backend).and_return(@backend)
@bucket = Ripple.client.bucket("widgets")
@widget = Widget.new(:size => 1000)
end
+ it "forces the content type to 'application/json'" do
+ @widget.robject.content_type = 'application/not-json'
+
+ @backend.should_receive(:store_object) do |obj, *_|
+ obj.content_type.should == 'application/json'
+ end
+
+ @widget.save
+ end
+
it "should save a new object to Riak" do
json = @widget.attributes.merge("_type" => "Widget").to_json
@backend.should_receive(:store_object) do |obj, _, _, _|
obj.raw_data.should == json
obj.key.should be_nil
@@ -110,29 +107,33 @@
@widget.should_not be_a_new_record
@widget.changes.should be_blank
end
it "should allow unexpected exceptions to be raised" do
- robject = mock("robject", :key => @widget.key, "data=" => true)
+ robject = mock("robject", :key => @widget.key, "data=" => true, "content_type=" => true)
robject.should_receive(:store).and_raise(Riak::HTTPFailedRequest.new(:post, 200, 404, {}, "404 not found"))
@widget.stub!(:robject).and_return(robject)
lambda { @widget.save }.should raise_error(Riak::FailedRequest)
end
- it "should reload a saved object" do
+ it "should reload a saved object, including associations" do
json = @widget.attributes.merge(:_type => "Widget").to_json
@backend.should_receive(:store_object) do |obj, _, _, _|
obj.raw_data.should == json
obj.key.should be_nil
# Simulate loading the response with the key
obj.key = "new_widget"
end
@widget.save
@backend.should_receive(:reload_object) do |obj, _|
obj.key.should == "new_widget"
+ obj.content_type = 'application/json'
obj.raw_data = '{"name":"spring","size":10,"shipped_at":"Sat, 01 Jan 2000 20:15:01 -0000","_type":"Widget"}'
+ obj
end
+
+ @widget.widget_parts.should_receive(:reset)
@widget.reload
@widget.changes.should be_blank
@widget.name.should == "spring"
@widget.size.should == 10
@widget.shipped_at.should == Time.utc(2000,"jan",1,20,15,1)
@@ -148,11 +149,11 @@
@widget.should be_frozen
end
it "should destroy all saved objects" do
@widget.should_receive(:destroy).and_return(true)
- Widget.should_receive(:all).and_yield(@widget)
+ Widget.should_receive(:list).and_yield(@widget)
Widget.destroy_all.should be_true
end
it "should freeze an unsaved object when destroying" do
@backend.should_not_receive(:delete_object)
@@ -205,8 +206,123 @@
widget = Widget.new
widget.key = "gear"
widget.instance_variable_set(:@new, false)
widget.send(:robject).should_receive(:delete).with({:rw => 1})
widget.destroy
+ end
+ end
+
+ shared_examples_for "saving a parent document with linked child documents" do
+ before(:each) do
+ @backend.stub(:store_object)
+ end
+
+ it 'saves new children when the parent is saved' do
+ children.each do |child|
+ child.stub(:new? => true)
+ child.should_receive(:save)
+ end
+ parent.save
+ end
+
+ it 'saves children that have changes when the parent is saved' do
+ children.each do |child|
+ child.stub(:new? => false)
+ child.stub(:changed? => true)
+ child.should_receive(:save)
+ end
+ parent.save
+ end
+
+ it 'does not save children that have no changes and are not new when the parent is saved' do
+ children.each do |child|
+ child.stub(:new? => false)
+ child.stub(:changed? => false)
+ child.should_not_receive(:save)
+ end
+ parent.save
+ end
+ end
+
+ context "for a document with a many linked association" do
+ before(:all) do
+ # check assumptions of these examples
+ Widget.associations[:widget_parts].should be_many
+ Widget.associations[:widget_parts].should be_linked
+ end
+
+ it_behaves_like "saving a parent document with linked child documents" do
+ let(:parent) { Widget.new(:name => 'fizzbuzz') }
+ let(:children) { %w[ fizz buzz ].map { |n| WidgetPart.new(:name => n) } }
+
+ before(:each) do
+ children.each { |c| parent.widget_parts << c }
+ end
+ end
+ end
+
+ describe "for a document with a one linked association" do
+ before(:all) do
+ # check assumptions of these examples
+ Invoice.associations[:customer].should be_one
+ Invoice.associations[:customer].should be_linked
+ end
+
+ it_behaves_like "saving a parent document with linked child documents" do
+ let(:parent) { Invoice.new }
+ let(:children) { [Customer.new] }
+
+ before(:each) do
+ parent.customer = children.first
+ end
+ end
+ end
+
+ shared_examples_for "embedded association persistence logic" do
+ before(:each) do
+ @backend.stub(:store_object)
+ end
+
+ it "does not save children when the parent is saved" do
+ children.each do |child|
+ child.stub(:new? => true, :changed? => true)
+ child.should_not_receive(:save)
+ end
+
+ parent.save
+ end
+ end
+
+ describe "for a document with a many embedded association" do
+ before(:all) do
+ # check assumptions of these examples
+ Clock.associations[:modes].should be_many
+ Clock.associations[:modes].should be_embedded
+ end
+
+ it_behaves_like "embedded association persistence logic" do
+ let(:parent) { Clock.new }
+ let(:children) { [1, 2].map { |i| Mode.new } }
+
+ before(:each) do
+ children.each { |c| parent.modes << c }
+ end
+ end
+ end
+
+ describe "for a document with a one embedded association" do
+ before(:all) do
+ # check assumptions of these examples
+ Parent.associations[:child].should be_one
+ Parent.associations[:child].should be_embedded
+ end
+
+ it_behaves_like "embedded association persistence logic" do
+ let(:parent) { Parent.new }
+ let(:children) { [Child.new(:name => 'Bobby', :age => 9)] }
+
+ before(:each) do
+ parent.child = children.first
+ end
end
end
end