spec/dynamoid/persistence_spec.rb in dynamoid-0.6.1 vs spec/dynamoid/persistence_spec.rb in dynamoid-0.7.0
- old
+ new
@@ -31,11 +31,29 @@
it 'assigns itself an id on save' do
@address.save
Dynamoid::Adapter.read("dynamoid_tests_addresses", @address.id)[:id].should == @address.id
end
-
+
+ it 'prevents concurrent writes to tables with a lock_version' do
+ @address.save!
+ a1 = @address
+ a2 = Address.find(@address.id)
+
+ a1.city = 'Seattle'
+ a2.city = 'San Francisco'
+
+ a1.save!
+ expect { a2.save! }.to raise_exception(Dynamoid::Errors::ConditionalCheckFailedException)
+ end
+
+ configured_with 'partitioning' do
+ it 'raises an error when attempting to use optimistic locking' do
+ expect { address.save! }.to raise_exception
+ end
+ end
+
it 'assigns itself an id on save only if it does not have one' do
@address.id = 'test123'
@address.save
Dynamoid::Adapter.read("dynamoid_tests_addresses", 'test123').should_not be_empty
@@ -87,18 +105,18 @@
it 'dumps and undump a serialized field' do
@address.options = (hash = {:x => [1, 2], "foobar" => 3.14})
Address.undump(@address.send(:dump))[:options].should == hash
end
-
+
[true, false].each do |bool|
it "dumps a #{bool} boolean field" do
@address.deliverable = bool
Address.undump(@address.send(:dump))[:deliverable].should == bool
end
end
-
+
it 'raises on an invalid boolean value' do
expect do
@address.deliverable = true
data = @address.send(:dump)
data[:deliverable] = 'foo'
@@ -140,24 +158,24 @@
it 'works with a HashWithIndifferentAccess' do
hash = ActiveSupport::HashWithIndifferentAccess.new("city" => "Atlanta")
lambda {Address.create(hash)}.should_not raise_error
end
-
+
context 'create' do
{
Tweet => ['with range', { :tweet_id => 1, :group => 'abc' }],
Message => ['without range', { :message_id => 1, :text => 'foo', :time => DateTime.now }]
}.each_pair do |clazz, fields|
it "checks for existence of an existing object #{fields[0]}" do
t1 = clazz.new(fields[1])
t2 = clazz.new(fields[1])
-
+
t1.save
expect do
t2.save!
- end.to raise_exception AWS::DynamoDB::Errors::ConditionalCheckFailedException
+ end.to raise_exception Dynamoid::Errors::ConditionalCheckFailedException
end
end
end
context 'unknown fields' do
@@ -175,26 +193,42 @@
it 'raises when undumping a column with an unknown field type' do
expect do
clazz.new(:deliverable => true) #undump is called here
end.to raise_error(ArgumentError)
end
-
+
it 'raises when dumping a column with an unknown field type' do
doc = clazz.new
doc.deliverable = true
expect do
doc.dump
end.to raise_error(ArgumentError)
end
end
-
+
context 'update' do
before :each do
@tweet = Tweet.create(:tweet_id => 1, :group => 'abc', :count => 5, :tags => ['db', 'sql'], :user_name => 'john')
end
+ it 'runs before_update callbacks when doing #update' do
+ CamelCase.any_instance.expects(:doing_before_update).once.returns(true)
+
+ CamelCase.create(:color => 'blue').update do |t|
+ t.set(:color => 'red')
+ end
+ end
+
+ it 'runs after_update callbacks when doing #update' do
+ CamelCase.any_instance.expects(:doing_after_update).once.returns(true)
+
+ CamelCase.create(:color => 'blue').update do |t|
+ t.set(:color => 'red')
+ end
+ end
+
it 'support add/delete operation on a field' do
@tweet.update do |t|
t.add(:count => 3)
t.delete(:tags => ['db'])
end
@@ -220,17 +254,48 @@
@tweet.update!(:if => { :count => 5 }) do |t|
t.add(:count => 3)
end
}.to raise_error(Dynamoid::Errors::ConditionalCheckFailedException)
end
+
+ it 'prevents concurrent saves to tables with a lock_version' do
+ @address.save!
+ a2 = Address.find(@address.id)
+ a2.update! { |a| a.set(:city => "Chicago") }
+
+ expect do
+ @address.city = "Seattle"
+ @address.save!
+ end.to raise_error(Dynamoid::Errors::ConditionalCheckFailedException)
+ end
end
context 'delete' do
it 'deletes model with datetime range key' do
lambda {
msg = Message.create!(:message_id => 1, :time => DateTime.now, :text => "Hell yeah")
msg.destroy
}.should_not raise_error
+ end
+ end
+
+ context 'single table inheritance' do
+ let(:car) { Car.create(power_locks: false) }
+ let(:sub) { NuclearSubmarine.create(torpedoes: 5) }
+
+ it 'saves subclass objects in the parent table' do
+ c = car
+ Vehicle.find(c.id).should == c
+ end
+
+ it 'loads subclass item when querying the parent table' do
+ c = car
+ s = sub
+
+ Vehicle.all.to_a.tap { |v|
+ v.should include(c)
+ v.should include(s)
+ }
end
end
end