Skip to content

Commit

Permalink
Rename PartialUpdating to AtomicUpdates.
Browse files Browse the repository at this point in the history
Now optional as well.
  • Loading branch information
jnunemaker committed May 20, 2012
1 parent a7cf2f5 commit d60b6d4
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 140 deletions.
3 changes: 1 addition & 2 deletions lib/toy/mongo.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
require 'toy/extensions/bson_object_id'
require 'toy/identity/object_id_key_factory'
require 'toy/mongo/querying'
require 'toy/mongo/partial_updating'
require 'toy/mongo/atomic_updates'
require 'adapter/mongo'

module Toy
Expand All @@ -15,7 +15,6 @@ class Error < StandardError; end
included do
include Toy::Store
include Querying
include PartialUpdating

key Toy::Identity::ObjectIdKeyFactory.new
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,9 @@ def initialize(name)
end
end

module PartialUpdating
module AtomicUpdates
extend ActiveSupport::Concern

included do
class_attribute :partial_updates

self.partial_updates = false
end

module ClassMethods
def use_partial_updates
if adapter.name != :mongo_atomic
raise IncompatibleAdapter.new(adapter.name)
end

self.partial_updates = true
end
end

# Very basic method for determining what has changed locally
# so we can just update changes instead of entire document
#
Expand All @@ -43,19 +27,16 @@ def persistable_changes
end

def persist
if partial_updates?
if new_record?
adapter.write id, persisted_attributes
else
updates = persistable_changes
if updates.present?
adapter.write id, updates
end
end
if new_record?
adapter.write id, persisted_attributes
else
super
updates = persistable_changes
if updates.present?
adapter.write id, updates
end
end
end
private :persist

def atomic_update(update, opts={})
options = {}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
require 'helper'

describe Toy::Mongo::PartialUpdating do
describe Toy::Mongo::AtomicUpdates do
uses_constants 'User'

before do
User.send :include, Toy::Mongo::AtomicUpdates
User.adapter :mongo_atomic, STORE
end

describe "#persistable_changes" do
before(:each) do
User.attribute :name, String
Expand Down Expand Up @@ -96,129 +101,63 @@
end
end

describe ".partial_updates" do
before do
User.adapter :mongo_atomic, STORE
end
describe "#persist" do
it "only persists changes" do
User.attribute :name, String
User.attribute :bio, String

it "defaults to false" do
User.partial_updates.should be_false
end
user = User.create(:name => 'John', :bio => 'Awesome.')
user.name = 'Johnny'

it "can be turned on" do
User.use_partial_updates
User.partial_updates.should be_true
end
# simulate outside change
user.adapter.client.update({:_id => user.id}, {'$set' => {:bio => 'Surprise!'}})

it "is inherited" do
User.use_partial_updates
subclass = Class.new(User)
subclass.partial_updates.should be_true
end
user.save
user.reload

it "is inherited separate from superclass" do
User.use_partial_updates
subclass = Class.new(User)
subclass.partial_updates = false
User.partial_updates.should be_true
subclass.partial_updates.should be_false
user.name.should eq('Johnny')
user.bio.should eq('Surprise!')
end

it "raises an error if not using mongo_atomic" do
User.adapter :mongo, STORE

expect {
User.use_partial_updates
}.to raise_error Toy::Mongo::IncompatibleAdapter, "In order to use partial updates, you need to be using the :mongo_atomic adapter, but you are using :mongo"
it "persists default values that did not change" do
User.attribute :version, Integer, :default => 1
user = User.new
user.adapter.should_receive(:write).with(user.id, {
'version' => 1,
})
user.save
end
end

describe "#persist" do
context "with partial updates on" do
before do
User.adapter :mongo_atomic, STORE
User.partial_updates = true
end

it "only persists changes" do
User.attribute :name, String
User.attribute :bio, String

user = User.create(:name => 'John', :bio => 'Awesome.')
user.name = 'Johnny'

# simulate outside change
user.adapter.client.update({:_id => user.id}, {'$set' => {:bio => 'Surprise!'}})

user.save
user.reload

user.name.should eq('Johnny')
user.bio.should eq('Surprise!')
end

it "persists default values that did not change" do
User.attribute :version, Integer, :default => 1
user = User.new
user.adapter.should_receive(:write).with(user.id, {
'version' => 1,
})
user.save
end

it "does not persist virtual attributes" do
User.attribute :name, String
User.attribute :password, String, :virtual => true

user = User.new(:name => 'John')
user.password = 'hacks'
user.adapter.should_receive(:write).with(user.id, {
'name' => 'John',
})
user.save
end

it "does persist new records even without changes" do
user = User.create
user.persisted?.should be_true
end

it "does not persist if there were no changes" do
user = User.create
user.adapter.should_not_receive(:write)
user.save
end
it "does not persist virtual attributes" do
User.attribute :name, String
User.attribute :password, String, :virtual => true

it "works with abbreviated attributes" do
User.attribute :email, String, :abbr => :e
user = User.new(:email => 'john@doe.com')
user.adapter.should_receive(:write).with(user.id, {
'e' => 'john@doe.com',
})
user.save
end
user = User.new(:name => 'John')
user.password = 'hacks'
user.adapter.should_receive(:write).with(user.id, {
'name' => 'John',
})
user.save
end

context "with partial updates off" do
before do
User.attribute :name, String
User.attribute :bio, String
User.partial_updates = false
end

it "persists entire document blowing away outside changes" do
user = User.create(:name => 'John', :bio => 'Awesome.')
user.name = 'Johnny'

# simulate outside change
user.adapter.client.update({:_id => user.id}, {'$set' => {:bio => 'Surprise!'}})
it "does persist new records even without changes" do
user = User.create
user.persisted?.should be_true
end

user.save
user.reload
it "does not persist if there were no changes" do
user = User.create
user.adapter.should_not_receive(:write)
user.save
end

user.name.should eq('Johnny')
user.bio.should eq('Awesome.')
end
it "works with abbreviated attributes" do
User.attribute :email, String, :abbr => :e
user = User.new(:email => 'john@doe.com')
user.adapter.should_receive(:write).with(user.id, {
'e' => 'john@doe.com',
})
user.save
end
end
end

0 comments on commit d60b6d4

Please sign in to comment.