Skip to content
This repository has been archived by the owner on Sep 7, 2021. It is now read-only.

Commit

Permalink
refactor tracking changes; fix bug with inspect in Rails
Browse files Browse the repository at this point in the history
  • Loading branch information
mislav committed Sep 11, 2010
1 parent 07f5ef0 commit e16f8c0
Showing 1 changed file with 60 additions and 11 deletions.
71 changes: 60 additions & 11 deletions lib/mingo.rb
@@ -1,3 +1,4 @@
require 'active_support/core_ext/hash/conversions'
require 'mongo'
require 'active_model'
require 'hashie/dash'
Expand Down Expand Up @@ -72,7 +73,7 @@ def many(property, model, &block)
attr_reader :changes

def initialize(obj = nil)
@changes = Hash.new { |c, key| c[key] = [self[key]] }
@changes = {}
@destroyed = false

if obj and obj['_id'].is_a? BSON::ObjectId
Expand All @@ -93,6 +94,10 @@ def []=(property, value)
_regular_writer(property.to_s, value)
end

# keys are already strings
def stringify_keys() self end
alias :stringify_keys! :stringify_keys

def id
self['_id']
end
Expand Down Expand Up @@ -148,10 +153,17 @@ def values_for_update
end

def _regular_writer(key, value)
old_value = _regular_reader(key)
changes[key.to_sym][1] = value unless value == old_value
track_change(key, value)
super
end

def track_change(key, value)
old_value = _regular_reader(key)
unless value == old_value
memo = (changes[key.to_sym] ||= [old_value])
memo[0] == value ? changes.delete(key.to_sym) : (memo[1] = value)
end
end
end

if $0 == __FILE__
Expand All @@ -169,19 +181,34 @@ class User < Mingo
User.collection.remove
end

it "obtains an ID by saving" do
user = build :name => 'Mislav'
user.should_not be_persisted
user.id.should be_nil
user.save
raw_doc(user.id)['name'].should == 'Mislav'
user.should be_persisted
user.id.should be_a(BSON::ObjectId)
end

it "tracks changes attribute" do
user = build
user.should_not be_persisted
user.should_not be_changed
user.name = 'Mislav'
user.should be_changed
user.changes.keys.should include(:name)
user.name = 'Mislav2'
user.changes[:name].should == [nil, 'Mislav2']
user.save
user.should be_persisted
user.should_not be_changed
user.id.should be_a(BSON::ObjectId)
end

it "forgets changed attribute when reset to original value" do
user = create :name => 'Mislav'
user.name = 'Mislav2'
user.should be_changed
user.name = 'Mislav'
user.should_not be_changed
end

it "has a human model name" do
Expand Down Expand Up @@ -218,11 +245,33 @@ class User < Mingo
end
end

it "finds a doc by string ID" do
user = create :name => 'Mislav'
user_dup = described_class.first(user.id.to_s)
user_dup.id.should == user.id
user_dup.name.should == 'Mislav'
context "existing doc" do
before do
@id = described_class.collection.insert :name => 'Mislav', :age => 26
end

it "finds a doc by string ID" do
user = described_class.first(@id.to_s)
user.id.should == @id
user.name.should == 'Mislav'
user.age.should == 26
end

it "is unchanged after loading" do
user = described_class.first(@id)
user.should_not be_changed
user.age = 27
user.should be_changed
user.changes.keys.should == [:age]
end

it "doesn't get changed by an inspect" do
user = described_class.first(@id)
# triggers AS stringify_keys, which dups the Dash and writes to it,
# which mutates the @changes hash from the original Dash
user.inspect
user.should_not be_changed
end
end

it "returns nil for non-existing doc" do
Expand Down

0 comments on commit e16f8c0

Please sign in to comment.