diff --git a/lib/strokedb.rb b/lib/strokedb.rb index 8e315218..2b93ad1f 100644 --- a/lib/strokedb.rb +++ b/lib/strokedb.rb @@ -70,6 +70,7 @@ def DEBUG class NoDefaultStoreError < Exception ; end end +require 'strokedb/nsurl' require 'strokedb/util' require 'strokedb/document' require 'strokedb/config' diff --git a/lib/strokedb/core_ext/string.rb b/lib/strokedb/core_ext/string.rb index d360db6c..44440153 100644 --- a/lib/strokedb/core_ext/string.rb +++ b/lib/strokedb/core_ext/string.rb @@ -25,11 +25,15 @@ def demodulize gsub(/^.*::/, '') end + def modulize + return '' unless include?('::') && self[0,2] != '::' + self.gsub(/^(.+)::(#{demodulize})$/,'\\1') + end + def constantize unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ self raise NameError, "#{self.inspect} is not a valid constant name!" end - Object.module_eval("::#{$1}", __FILE__, __LINE__) end diff --git a/lib/strokedb/document.rb b/lib/strokedb/document.rb index 02eb2f96..2c8376b1 100644 --- a/lib/strokedb/document.rb +++ b/lib/strokedb/document.rb @@ -684,11 +684,15 @@ def self.collect_meta_modules(store, meta) #:nodoc: case meta when VERSIONREF if m = store.find($1, $2) - meta_names << m[:name] + mod = Module.find_by_nsurl(m[:nsurl]) + mod = nil if mod == Module + meta_names << (mod ? mod.name : "") + "::" + m[:name] end when DOCREF if m = store.find($1) - meta_names << m[:name] + mod = Module.find_by_nsurl(m[:nsurl]) + mod = nil if mod == Module + meta_names << (mod ? mod.name : "") + "::" + m[:name] end when Array meta_names = meta.map { |m| collect_meta_modules(store, m) }.flatten diff --git a/lib/strokedb/document/delete.rb b/lib/strokedb/document/delete.rb index d50f6a78..0baeeced 100644 --- a/lib/strokedb/document/delete.rb +++ b/lib/strokedb/document/delete.rb @@ -3,7 +3,7 @@ module StrokeDB class DocumentDeletionError < StandardError end - DeletedDocument = Meta.new(:nsurl => STROKEDB_NSURL) do + DeletedDocument = Meta.new do on_load do |doc| doc.make_immutable! end diff --git a/lib/strokedb/document/meta.rb b/lib/strokedb/document/meta.rb index 303e31ff..544987d1 100644 --- a/lib/strokedb/document/meta.rb +++ b/lib/strokedb/document/meta.rb @@ -22,15 +22,6 @@ module StrokeDB module Meta class << self - - def default_nsurl - @default_nsurl ||= "" - end - - def default_nsurl=(nsurl) - @default_nsurl = nsurl - end - def new(*args, &block) mod = Module.new args = args.unshift(nil) if args.empty? || args.first.is_a?(Hash) @@ -62,7 +53,7 @@ def new(*args, &block) def document(store=nil) raise NoDefaultStoreError.new unless store ||= StrokeDB.default_store unless meta_doc = store.find(uuid) - meta_doc = Document.create!(store, :name => Meta.name, :uuid => uuid, :nsurl => STROKEDB_NSURL) + meta_doc = Document.create!(store, :name => Meta.name.demodulize, :uuid => uuid, :nsurl => StrokeDB.nsurl) end meta_doc end @@ -71,7 +62,7 @@ def document(store=nil) private def uuid - @uuid ||= ::Util.sha1_uuid("meta:#{STROKEDB_NSURL}##{Meta.name}") + @uuid ||= ::Util.sha1_uuid("meta:#{StrokeDB.nsurl}##{Meta.name.demodulize}") end def extract_meta_name(*args) @@ -243,8 +234,8 @@ def make_document(store=nil) values = @args.clone.select{|a| a.is_a?(Hash) }.first values[:meta] = Meta.document(store) - values[:name] ||= name - values[:nsurl] ||= Meta.default_nsurl + values[:name] ||= name.demodulize + values[:nsurl] ||= name.modulize.empty? ? Module.nsurl : name.modulize.constantize.nsurl values[:uuid] ||= ::Util.sha1_uuid("meta:#{values[:nsurl]}##{values[:name]}") if values[:name] if meta_doc = find_meta_doc(values, store) diff --git a/lib/strokedb/nsurl.rb b/lib/strokedb/nsurl.rb new file mode 100644 index 00000000..a60a32bc --- /dev/null +++ b/lib/strokedb/nsurl.rb @@ -0,0 +1,23 @@ +Module.module_eval do + + def self.clear_nsurls + @@nsurls = {} + end + def self.find_by_nsurl(url) + @@nsurls[url] + end + + def nsurl(url = nil) + return @nsurl unless url + @@nsurls ||= {} + mod = @@nsurls[url] + raise ArgumentError, "nsurl #{url.inspect} is already referenced by #{mod.inspect} module" if mod && mod != self + @@nsurls.delete(url) + @@nsurls[url] = self + @nsurl = url + end + +end + +Module.nsurl '' +StrokeDB.nsurl StrokeDB::STROKEDB_NSURL \ No newline at end of file diff --git a/lib/strokedb/store.rb b/lib/strokedb/store.rb index 64715914..85e36317 100644 --- a/lib/strokedb/store.rb +++ b/lib/strokedb/store.rb @@ -1,6 +1,6 @@ module StrokeDB - StoreInfo = Meta.new(:nsurl => STROKEDB_NSURL) + StoreInfo = Meta.new class Store include Enumerable diff --git a/lib/strokedb/sync/diff.rb b/lib/strokedb/sync/diff.rb index a9c4324a..4aeb09a7 100644 --- a/lib/strokedb/sync/diff.rb +++ b/lib/strokedb/sync/diff.rb @@ -68,7 +68,7 @@ def self.patch(from, patch) end end - Diff = Meta.new(:nsurl => STROKEDB_NSURL) do + Diff = Meta.new do on_initialization do |diff| diff.added_slots = {} unless diff[:added_slots] diff --git a/lib/strokedb/sync/store_sync.rb b/lib/strokedb/sync/store_sync.rb index 94646435..df34553c 100644 --- a/lib/strokedb/sync/store_sync.rb +++ b/lib/strokedb/sync/store_sync.rb @@ -1,6 +1,6 @@ module StrokeDB - SynchronizationReport = Meta.new(:nsurl => STROKEDB_NSURL) do + SynchronizationReport = Meta.new do on_new_document do |report| report.conflicts = [] report.added_documents = [] @@ -9,7 +9,7 @@ module StrokeDB end end - SynchronizationConflict = Meta.new(:nsurl => STROKEDB_NSURL) do + SynchronizationConflict = Meta.new do def resolve! # by default, do nothing end diff --git a/lib/strokedb/views/view.rb b/lib/strokedb/views/view.rb index 40f5eb8d..a2446540 100644 --- a/lib/strokedb/views/view.rb +++ b/lib/strokedb/views/view.rb @@ -234,7 +234,7 @@ def self.[](view_name) end class << View - def [](name, nsurl = Meta.default_nsurl) # FIXME: Meta seems to be a bad place for default_nsurl now + def [](name, nsurl = name.modulize.empty? ? Module.nsurl : name.modulize.constantize.nsurl) # FIXME: it is not nice uuid = ::Util.sha1_uuid("view:#{nsurl}##{name}") StrokeDB.default_store.find(uuid) end @@ -260,7 +260,7 @@ def new(*args, &block) raise ArgumentError, "View name must be specified!" end - nsurl = options['nsurl'] ||= Meta.default_nsurl # FIXME: Meta seems to be a bad place for default_nsurl now + nsurl = options['nsurl'] ||= name.modulize.empty? ? Module.nsurl : name.modulize.constantize.nsurl # FIXME: it is not nice (and the same shit is in meta.rb) options['uuid'] = ::Util.sha1_uuid("view:#{nsurl}##{name}") diff --git a/spec/lib/strokedb/core_ext/string_spec.rb b/spec/lib/strokedb/core_ext/string_spec.rb index c9afa19d..dd211c2a 100644 --- a/spec/lib/strokedb/core_ext/string_spec.rb +++ b/spec/lib/strokedb/core_ext/string_spec.rb @@ -5,4 +5,21 @@ "lib"/"core_ext".should == "lib/core_ext" "lib/core_ext"/"foo".should == "lib/core_ext/foo" end +end + +describe "String#modulize" do + + it "if there is no module, leave nothing" do + "A".modulize.should == "" + "::A".modulize.should == "" + end + + it "should leave single module" do + "A::B".modulize.should == "A" + end + + it "should leave multiple modules" do + "A::B::C".modulize.should == "A::B" + end + end \ No newline at end of file diff --git a/spec/lib/strokedb/document/meta_meta_spec.rb b/spec/lib/strokedb/document/meta_meta_spec.rb index 41c61457..27efb0e7 100644 --- a/spec/lib/strokedb/document/meta_meta_spec.rb +++ b/spec/lib/strokedb/document/meta_meta_spec.rb @@ -10,16 +10,6 @@ it "should have nsurl http://strokedb.com/" do Meta.document.nsurl.should == STROKEDB_NSURL end - - it "should have blank default nsurl by default" do - Meta.default_nsurl.should be_blank - end - - it "should be able to configure new default nsurl" do - Meta.default_nsurl = "http://mycoolapp.com" - Meta.default_nsurl.should == "http://mycoolapp.com" - Meta.default_nsurl = "" - end end diff --git a/spec/lib/strokedb/document/meta_spec.rb b/spec/lib/strokedb/document/meta_spec.rb index aa9a0768..49a2d3db 100644 --- a/spec/lib/strokedb/document/meta_spec.rb +++ b/spec/lib/strokedb/document/meta_spec.rb @@ -2,18 +2,6 @@ describe "Meta module", :shared => true do - it "should use Meta.default_nsurl if nsurl is not specified" do - Meta.default_nsurl = "http://some/" - SomeName.document.nsurl.should == "http://some/" - end - - it "should not use Meta.default_nsurl if nsurl is specified" do - Meta.default_nsurl = "http://some/" - Object.send!(:remove_const,'SomeName') if defined?(SomeName) - SomeName = Meta.new(:nsurl => "http://another/") - SomeName.document.nsurl.should == "http://another/" - end - it "should be able to instantiate new Document which is also SomeName" do obj = SomeName.new obj.should be_a_kind_of(Document) @@ -174,6 +162,58 @@ end end +describe "Meta module within no module" do + + before(:each) do + setup_default_store + setup_index + + Object.send!(:remove_const,'SomeName') if defined?(SomeName) + end + + it "should use Module.nsurl by default" do + Module.nsurl "test" + SomeName = Meta.new + SomeName.document.nsurl.should == Module.nsurl + Module.nsurl '' + end + + it "should not use Module.nsurl if nsurl is specified" do + Module.nsurl "test" + SomeName = Meta.new(:nsurl => 'passed') + SomeName.document.nsurl.should == 'passed' + Module.nsurl '' + end + +end + + +describe "Meta module within module" do + + before(:each) do + setup_default_store + setup_index + module A + nsurl "some url" + end + A.send!(:remove_const,'SomeName') if defined?(A::SomeName) + end + + it "should use Module.nsurl by default" do + module A + SomeName = Meta.new + end + A::SomeName.document.nsurl.should == A.nsurl + end + + it "should not use Module.nsurl if nsurl is specified" do + module A + SomeName = Meta.new(:nsurl => "nsurl") + end + A::SomeName.document.nsurl.should == "nsurl" + end + +end describe "Meta module with on_initialization callback" do before(:each) do @@ -228,7 +268,7 @@ doc = SomeName.new end - it "should receive this callback on document load" do + it "should receive this callback on document load" do doc = SomeName.create! Kernel.should_receive(:on_load_called).with(false) SomeName.find(doc.uuid) diff --git a/spec/lib/strokedb/nsurl_spec.rb b/spec/lib/strokedb/nsurl_spec.rb new file mode 100644 index 00000000..48472905 --- /dev/null +++ b/spec/lib/strokedb/nsurl_spec.rb @@ -0,0 +1,60 @@ +require File.dirname(__FILE__) + '/spec_helper' + +describe "Some", Module do + + before(:each) do + @module = Module.new + Module.clear_nsurls + end + + it "should have nil nsurl by default" do + @module.nsurl.should be_nil + end + + it "should be able to change nsurl" do + @module.nsurl 'http://some.url' + @module.nsurl.should == 'http://some.url' + end + + it "should be findable by nsurl" do + @module.nsurl 'http://some.url' + Module.find_by_nsurl(@module.nsurl).should == @module + end + + it "should be able to change nsurl to the same value" do + @module.nsurl 'http://some.url' + lambda { @module.nsurl 'http://some.url' }.should_not raise_error(ArgumentError) + end + + it "should not be able to change nsurl to the value already assigned to some module" do + @some_module = Module.new + @some_module.nsurl 'http://some.url' + lambda { @module.nsurl 'http://some.url' }.should raise_error(ArgumentError) + end + +end + +describe Module do + + + before(:each) do + Module.clear_nsurls + end + + it "should have empty nsurl by default" do + Module.nsurl.should be_empty + end + +end + +describe StrokeDB do + + before(:each) do + Module.clear_nsurls + end + + it "should have #{STROKEDB_NSURL} nsurl by default" do + StrokeDB.nsurl.should == STROKEDB_NSURL + end + +end \ No newline at end of file