diff --git a/lib/strokedb/document.rb b/lib/strokedb/document.rb
index 210c23e5..58d469bb 100644
--- a/lib/strokedb/document.rb
+++ b/lib/strokedb/document.rb
@@ -435,7 +435,7 @@ def save!(perform_validation = true)
# Updates slots with a specified hash and returns itself.
def update_slots(hash)
hash.each do |k, v|
- self[k] = v
+ self[k] = v unless self[k] == v
end
self
end
@@ -444,6 +444,7 @@ def update_slots(hash)
def update_slots!(hash)
update_slots(hash).save!
end
+
# Updates nil/false slots with a specified hash and returns itself.
# Already set slots are not modified (||= is used).
diff --git a/lib/strokedb/document/meta.rb b/lib/strokedb/document/meta.rb
index 889595f6..c882074b 100644
--- a/lib/strokedb/document/meta.rb
+++ b/lib/strokedb/document/meta.rb
@@ -118,6 +118,20 @@ def +(meta)
raise "Can't + #{self.class} and #{meta.class}"
end
end
+
+ def named(*args)
+ args.unshift StrokeDB.default_store unless args.first.is_a?(StrokeDB::Store)
+ args << {} unless args.last.is_a?(Hash)
+ raise InvalidArgumentError, "you should specify name" unless args[1].is_a?(String)
+ name = args[1]
+ uuid = ::StrokeDB::Util.sha1_uuid("#{document.uuid}:#{name}")
+ unless doc = find(args[0],uuid)
+ doc = create!(args[0],args.last.reverse_merge(:uuid => uuid))
+ else
+ doc.update_slots!(args.last)
+ end
+ doc
+ end
CALLBACKS = %w(on_initialization
on_load
@@ -205,7 +219,7 @@ def find(*args)
end
#
- # Conveniance alias for Meta#find.
+ # Convenience alias for Meta#find.
#
alias :all :find
diff --git a/spec/lib/strokedb/document/document_spec.rb b/spec/lib/strokedb/document/document_spec.rb
index ef22d147..df5a3744 100644
--- a/spec/lib/strokedb/document/document_spec.rb
+++ b/spec/lib/strokedb/document/document_spec.rb
@@ -90,6 +90,15 @@
@document.bbb.should == true
end
+ it "should batch update slots but should not touch version/previous_version if update haven't changed document" do
+ @document = @document.update_slots!(:aaa => "aaa", :bbb => true).reload
+ lambda do
+ lambda do
+ @document.update_slots(:aaa => "aaa", :bbb => true)
+ end.should_not change(@document, :version)
+ end.should_not change(@document, :previous_version)
+ end
+
it "should not save batch update slots" do
@document.save! # ensure it is not new
doc = @document.reload
diff --git a/spec/lib/strokedb/document/meta_spec.rb b/spec/lib/strokedb/document/meta_spec.rb
index 20f4aa79..e13f94ab 100644
--- a/spec/lib/strokedb/document/meta_spec.rb
+++ b/spec/lib/strokedb/document/meta_spec.rb
@@ -363,4 +363,60 @@ def implements_some_name_meta
end
+end
+
+describe "Meta#named" do
+
+ before(:each) do
+ setup_default_store
+ setup_index
+ Object.send!(:remove_const,'SomeName') if defined?(SomeName)
+ SomeName = Meta.new
+ end
+
+ it "with (name) should create named document with this meta if it does not exist" do
+ doc = SomeName.named("hello")
+ doc.should_not be_nil
+ doc.should be_a_kind_of(Document)
+ doc.should be_a_kind_of(SomeName)
+ doc.should_not be_new
+ doc.versions.all.should have(1).item
+ end
+
+ it "with (name, slots hash) should create named document with this meta if it does not exist" do
+ doc = SomeName.named("hello", :some_slot => 1, :another_slot => "2")
+ doc.should_not be_nil
+ doc.should be_a_kind_of(Document)
+ doc.should be_a_kind_of(SomeName)
+ doc.should_not be_new
+ doc.versions.all.should have(1).item
+ doc.some_slot.should == 1
+ doc.another_slot.should == "2"
+ end
+
+ it "with (name) should find named document with this meta if it does exist" do
+ doc = SomeName.named("hello")
+ SomeName.named("hello").should == doc
+ end
+
+ it "with (name, slots hash) should find named document with this meta if it does exist" do
+ doc = SomeName.named("hello", :some_slot => 1, :another_slot => "2")
+ SomeName.named("hello", :some_slot => 1, :another_slot => "2").should == doc
+ end
+
+ it "with (name, slots hash) should find and updated named document with this meta if it does exist but has no such slot pairs" do
+ doc = SomeName.named("hello", :some_slot => 1)
+ new_doc = SomeName.named("hello", :some_slot => 1, :another_slot => "2")
+ new_doc.should_not == doc
+ new_doc.versions.previous.should == doc
+ new_doc.another_slot.should == "2"
+ new_doc = SomeName.named("hello", :some_slot => 2, :another_slot => "2")
+ new_doc.some_slot.should == 2
+ end
+
+ it "should be able to accept store as a first argument" do
+ doc = SomeName.named("hello")
+ SomeName.named(StrokeDB.default_store,"hello").should == doc
+ end
+
end
\ No newline at end of file