diff --git a/lib/mongo_mapper.rb b/lib/mongo_mapper.rb index c63661876..0938400b5 100644 --- a/lib/mongo_mapper.rb +++ b/lib/mongo_mapper.rb @@ -8,13 +8,11 @@ gem 'activesupport', '>= 2.3' gem 'mongo', '0.18.2' gem 'jnunemaker-validatable', '1.8.1' - gem 'moneta', '0.6.0' end require 'active_support' require 'mongo' require 'validatable' -require 'moneta' module MongoMapper # generic MM error diff --git a/lib/mongo_mapper/plugins/identity_map.rb b/lib/mongo_mapper/plugins/identity_map.rb index 0180bff60..553203955 100644 --- a/lib/mongo_mapper/plugins/identity_map.rb +++ b/lib/mongo_mapper/plugins/identity_map.rb @@ -1,17 +1,15 @@ -require 'moneta/memory' - module MongoMapper module Plugins module IdentityMap module ClassMethods def identity_map - Thread.current[:mongo_mapper_identity_map] + Thread.current[:mongo_mapper_identity_map] ||= {} end - + def identity_map=(v) Thread.current[:mongo_mapper_identity_map] = v end - + def identity_map_key(id) "#{self}:#{id}" end @@ -19,7 +17,7 @@ def identity_map_key(id) def find_one(options={}) criteria, options = to_finder_options(options) key = identity_map_key(criteria[:_id]) - + if document = identity_map[key] document else @@ -30,10 +28,8 @@ def find_one(options={}) def load(attrs) id = attrs[:_id] || attrs[:id] || attrs['_id'] || attrs['id'] key = identity_map_key(id) - - if document = identity_map[key] - document - else + + unless document = identity_map[key] document = super identity_map[document.identity_map_key] = document end @@ -41,27 +37,23 @@ def load(attrs) document end end - + module InstanceMethods - def self.included(model) - model.identity_map ||= Moneta::Memory.new - end - def identity_map_key @identity_map_key ||= self.class.identity_map_key(_id) end - + def identity_map self.class.identity_map end - + def save if result = super - identity_map.store(identity_map_key, self) + identity_map[identity_map_key] = self end result end - + def delete identity_map.delete(identity_map_key) super diff --git a/test/functional/test_identity_map.rb b/test/functional/test_identity_map.rb index e52432501..ee1b723ff 100644 --- a/test/functional/test_identity_map.rb +++ b/test/functional/test_identity_map.rb @@ -13,61 +13,86 @@ def assert_not_in_map(resource) context "Document" do setup do - @person_class = Doc('Person') do - key :name, String - end + @person_class = Doc('Person') { key :name, String } + @person_class.identity_map = {} - @post_class = Doc('Post') do - key :title, String - end + @post_class = Doc('Post') { key :title, String } + @post_class.identity_map = {} end - should "have an identity map method" do - map = @person_class.identity_map - map.should be_instance_of(Moneta::Memory) + should "default identity map to hash" do + map = Doc().identity_map + map.should == {} end - + should "share identity map with other classes" do map = @post_class.identity_map map.object_id.should == @person_class.identity_map.object_id end - - should "have identity map key that is always unique" do + + should "have identity map key that is always unique per document and class" do person = @person_class.new person.identity_map_key.should == "Person:#{person.id}" - + post = @post_class.new post.identity_map_key.should == "Post:#{post.id}" - + person.identity_map_key.should_not == post.identity_map_key end - + should "add key to map when saved" do person = @person_class.new assert_not_in_map(person) person.save.should be_true - + mapped_person = person.identity_map[person.identity_map_key] person.object_id.should == mapped_person.object_id end - + should "remove key from map when deleted" do - person = @person_class.create - + person = @person_class.create(:name => 'Fred') + assert_in_map(person) person.destroy assert_not_in_map(person) end - should "load object from identity map if exists" do - person = @person_class.create - assert_in_map(person) - - Mongo::Collection.any_instance.expects(:find).never - Mongo::Collection.any_instance.expects(:find_one).never - - found_person = @person_class.find(person.id) - found_person.object_id.should == person.object_id + context "find with one id" do + context "for object not in map" do + setup do + @person = @person_class.create(:name => 'Fred') + @person_class.identity_map.clear + end + + should "query the database" do + Mongo::Collection.any_instance.expects(:find_one).once + @person_class.find(@person.id) + end + + should "add object to map" do + assert_not_in_map(@person) + found_person = @person_class.find(@person.id) + assert_in_map(found_person) + end + end + + context "for object in map" do + setup do + @person = @person_class.create(:name => 'Fred') + end + + should "not query database" do + Mongo::Collection.any_instance.expects(:find).never + Mongo::Collection.any_instance.expects(:find_one).never + @person_class.find(@person.id) + end + + should "return exact object" do + assert_in_map(@person) + found_person = @person_class.find(@person.id) + found_person.object_id.should == @person.object_id + end + end end end end \ No newline at end of file