From 591e7fe8a219f16de2f3428dc01950a67c231e90 Mon Sep 17 00:00:00 2001 From: Yurii Rashkovskii Date: Wed, 30 Apr 2008 08:18:03 +0300 Subject: [PATCH] Metas without constant initial implementation [#30 state:resolved] --- lib/strokedb/core_ext/string.rb | 3 ++ lib/strokedb/document.rb | 13 +++++-- lib/strokedb/document/meta.rb | 39 +++++++++++++------- spec/lib/strokedb/document/meta_meta_spec.rb | 17 --------- spec/lib/strokedb/document/meta_spec.rb | 32 ++++++++++++++-- 5 files changed, 67 insertions(+), 37 deletions(-) diff --git a/lib/strokedb/core_ext/string.rb b/lib/strokedb/core_ext/string.rb index 44440153..3ed580cf 100644 --- a/lib/strokedb/core_ext/string.rb +++ b/lib/strokedb/core_ext/string.rb @@ -31,6 +31,9 @@ def modulize end def constantize + if /^meta:/ =~ self + return StrokeDB::META_CACHE[Meta.make_uuid_from_fullname(self)] + end unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ self raise NameError, "#{self.inspect} is not a valid constant name!" end diff --git a/lib/strokedb/document.rb b/lib/strokedb/document.rb index 2b1bbc1b..90b507e8 100644 --- a/lib/strokedb/document.rb +++ b/lib/strokedb/document.rb @@ -344,7 +344,6 @@ def self.from_raw(store, raw_slots, opts = {}) #:nodoc: collect_meta_modules(store, raw_slots['meta']).each do |meta_module| unless doc.is_a? meta_module doc.extend(meta_module) - meta_module.send!(:setup_callbacks, doc) rescue nil end end @@ -686,13 +685,21 @@ def self.collect_meta_modules(store, meta) #:nodoc: if m = store.find($1, $2) mod = Module.find_by_nsurl(m[:nsurl]) mod = nil if mod == Module - meta_names << (mod ? mod.name : "") + "::" + m[:name] + if (mod.nil? && Object.constants.include?(m[:name])) || (mod && mod.constants.include?(m[:name])) + meta_names << (mod ? mod.name : "") + "::" + m[:name] + else + meta_names << Meta.resolve_uuid_name(m[:nsurl],m[:name]) + end end when DOCREF if m = store.find($1) mod = Module.find_by_nsurl(m[:nsurl]) mod = nil if mod == Module - meta_names << (mod ? mod.name : "") + "::" + m[:name] + if (mod.nil? && Object.constants.include?(m[:name])) || (mod && mod.constants.include?(m[:name])) + meta_names << (mod ? mod.name : "") + "::" + m[:name] + else + meta_names << Meta.resolve_uuid_name(m[:nsurl],m[:name]) + end end when Array meta_names = meta.map { |m| collect_meta_modules(store, m) }.flatten diff --git a/lib/strokedb/document/meta.rb b/lib/strokedb/document/meta.rb index 8f41a425..6ed6f9c1 100644 --- a/lib/strokedb/document/meta.rb +++ b/lib/strokedb/document/meta.rb @@ -1,4 +1,7 @@ module StrokeDB + + META_CACHE = {} + # Meta is basically a type. Imagine the following document: # # some_apple: @@ -20,8 +23,21 @@ module StrokeDB # # Document class will be extended by modules Fruit and Product. module Meta - + class << self + + def resolve_uuid_name(nsurl,name) + "meta:#{nsurl}##{name}" + end + + def make_uuid_from_fullname(full_name) + StrokeDB::Util.sha1_uuid(full_name) + end + + def make_uuid(nsurl, name) + StrokeDB::Util.sha1_uuid("meta:#{nsurl}##{name}") + end + def new(*args, &block) mod = Module.new args = args.unshift(nil) if args.empty? || args.first.is_a?(Hash) @@ -44,8 +60,13 @@ def new(*args, &block) initialize_coercions initialize_virtualizations end - if meta_name = extract_meta_name(*args) - Object.const_set(meta_name, mod) + if name = args.last.stringify_keys['name'] + META_CACHE[make_uuid(args.last.stringify_keys['nsurl'],args.last.stringify_keys['name'])] = mod + mod.instance_eval %{ + def name + '#{name}' + end + } end mod end @@ -65,14 +86,6 @@ def uuid @uuid ||= ::Util.sha1_uuid("meta:#{StrokeDB.nsurl}##{Meta.name.demodulize}") end - def extract_meta_name(*args) - if args.first.is_a?(Hash) - args.first[:name] - else - args[1][:name] unless args.empty? - end - end - end def +(meta) @@ -227,8 +240,6 @@ def document(store=nil) metadocs.size > 1 ? metadocs.inject { |a, b| a + b }.make_immutable! : metadocs.first end - private - def make_document(store=nil) raise NoDefaultStoreError.new unless store ||= StrokeDB.default_store @meta_initialization_procs.each {|proc| proc.call }.clear @@ -237,7 +248,7 @@ def make_document(store=nil) values[:meta] = Meta.document(store) 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] + values[:uuid] ||= Meta.make_uuid(values[:nsurl],values[:name]) if values[:name] if meta_doc = find_meta_doc(values, store) values[:version] = meta_doc.version diff --git a/spec/lib/strokedb/document/meta_meta_spec.rb b/spec/lib/strokedb/document/meta_meta_spec.rb index 27efb0e7..0e7e8e0c 100644 --- a/spec/lib/strokedb/document/meta_meta_spec.rb +++ b/spec/lib/strokedb/document/meta_meta_spec.rb @@ -13,23 +13,6 @@ end -describe "Meta meta instantiation" do - - before(:each) do - # @store = mock("store") - # StrokeDB.stub!(:default_store).and_return(@store) - setup_default_store - Object.send!(:remove_const,'SomeName') if defined?(SomeName) - @meta = Meta.new(:name => "SomeName") - end - - it "should create new meta module and bind it to name passed" do - @meta.should be_a_kind_of(Meta) - SomeName.should == @meta - end - -end - describe "Meta meta instantiation with block specified" do before(:each) do diff --git a/spec/lib/strokedb/document/meta_spec.rb b/spec/lib/strokedb/document/meta_spec.rb index 49a2d3db..ceafc641 100644 --- a/spec/lib/strokedb/document/meta_spec.rb +++ b/spec/lib/strokedb/document/meta_spec.rb @@ -32,7 +32,7 @@ new_doc = nil 2.times do |i| Object.send!(:remove_const,'SomeName') if defined?(SomeName) - @meta = Meta.new(:name => "SomeName", :description => "Something") + SomeName = Meta.new(:description => "Something") new_doc = SomeName.document end new_doc.uuid.should == doc.uuid @@ -162,6 +162,33 @@ end end + +describe "Meta module without constant definition" do + + before(:each) do + setup_default_store + setup_index + @some_name = Meta.new(:name => 'SomeName') do + def some + end + end + end + + it "should not set respective constant" do + defined?(SomeName).should be_nil + end + + it "should have its name constantizeable anyway" do + Meta.resolve_uuid_name("","SomeName").constantize.should == @some_name + end + + it "should be loaded into document on its load" do + doc = @some_name.create!.reload + doc.should respond_to(:some) + end + +end + describe "Meta module within no module" do before(:each) do @@ -254,7 +281,6 @@ module A before(:each) do setup_default_store setup_index - Object.send!(:remove_const,'SomeName') if defined?(SomeName) SomeName = Meta.new do on_load do |obj| @@ -271,7 +297,7 @@ module A it "should receive this callback on document load" do doc = SomeName.create! Kernel.should_receive(:on_load_called).with(false) - SomeName.find(doc.uuid) + d = SomeName.find(doc.uuid) end