om 1.8.1 → 1.9.0.pre1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +1 -1
- data/container_spec.rb +14 -14
- data/lib/om.rb +12 -9
- data/lib/om/samples/mods_article.rb +9 -9
- data/lib/om/tree_node.rb +6 -6
- data/lib/om/version.rb +1 -1
- data/lib/om/xml.rb +33 -31
- data/lib/om/xml/container.rb +12 -12
- data/lib/om/xml/document.rb +19 -18
- data/lib/om/xml/dynamic_node.rb +50 -45
- data/lib/om/xml/named_term_proxy.rb +13 -13
- data/lib/om/xml/node_generator.rb +3 -3
- data/lib/om/xml/template_registry.rb +26 -18
- data/lib/om/xml/term.rb +46 -30
- data/lib/om/xml/term_value_operators.rb +56 -52
- data/lib/om/xml/term_xpath_generator.rb +57 -51
- data/lib/om/xml/terminology.rb +10 -8
- data/lib/om/xml/terminology_based_solrizer.rb +90 -0
- data/lib/om/xml/validation.rb +19 -19
- data/lib/om/xml/vocabulary.rb +4 -4
- data/lib/tasks/om.rake +6 -4
- data/om.gemspec +2 -1
- data/spec/fixtures/mods_article.rb +90 -0
- data/spec/fixtures/mods_articles/hydrangea_article1.xml +2 -2
- data/spec/integration/differentiated_elements_spec.rb +2 -2
- data/spec/integration/element_value_spec.rb +13 -13
- data/spec/integration/proxies_and_ref_spec.rb +15 -15
- data/spec/integration/querying_documents_spec.rb +18 -24
- data/spec/integration/rights_metadata_integration_example_spec.rb +18 -18
- data/spec/integration/selective_querying_spec.rb +1 -1
- data/spec/integration/serialization_spec.rb +13 -13
- data/spec/integration/set_reentrant_terminology_spec.rb +10 -10
- data/spec/integration/xpathy_stuff_spec.rb +16 -16
- data/spec/spec_helper.rb +2 -2
- data/spec/unit/container_spec.rb +29 -28
- data/spec/unit/document_spec.rb +50 -49
- data/spec/unit/dynamic_node_spec.rb +45 -57
- data/spec/unit/named_term_proxy_spec.rb +16 -16
- data/spec/unit/node_generator_spec.rb +7 -7
- data/spec/unit/nokogiri_sanity_spec.rb +30 -30
- data/spec/unit/om_spec.rb +5 -5
- data/spec/unit/template_registry_spec.rb +69 -69
- data/spec/unit/term_builder_spec.rb +77 -77
- data/spec/unit/term_spec.rb +73 -79
- data/spec/unit/term_value_operators_spec.rb +191 -186
- data/spec/unit/term_xpath_generator_spec.rb +43 -37
- data/spec/unit/terminology_builder_spec.rb +85 -85
- data/spec/unit/terminology_spec.rb +98 -98
- data/spec/unit/validation_spec.rb +22 -22
- data/spec/unit/xml_serialization_spec.rb +22 -21
- data/spec/unit/xml_spec.rb +7 -7
- data/spec/unit/xml_terminology_based_solrizer_spec.rb +109 -0
- metadata +57 -17
- checksums.yaml +0 -7
- data/.rspec +0 -1
- data/.rubocop.yml +0 -1
- data/.rubocop_todo.yml +0 -382
- data/.travis.yml +0 -10
- data/gemfiles/gemfile.rails3 +0 -11
- data/gemfiles/gemfile.rails4 +0 -10
data/Rakefile
CHANGED
data/container_spec.rb
CHANGED
@@ -3,34 +3,34 @@ require "nokogiri"
|
|
3
3
|
require "om"
|
4
4
|
|
5
5
|
describe "OM::XML::Container" do
|
6
|
-
|
6
|
+
|
7
7
|
before(:all) do
|
8
8
|
class ContainerTest
|
9
9
|
include OM::XML::Container
|
10
10
|
end
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
before(:each) do
|
14
14
|
@container = ContainerTest.from_xml("<foo><bar>1</bar></foo>")
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
it "should add .ng_xml accessor" do
|
18
18
|
@container.should respond_to(:ng_xml)
|
19
|
-
@container.should respond_to(:ng_xml=)
|
19
|
+
@container.should respond_to(:ng_xml=)
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
describe "new" do
|
23
23
|
it "should populate ng_xml with an instance of Nokogiri::XML::Document" do
|
24
24
|
@container.ng_xml.class.should == Nokogiri::XML::Document
|
25
25
|
end
|
26
26
|
end
|
27
|
-
|
27
|
+
|
28
28
|
describe '#xml_template' do
|
29
29
|
it "should return an empty xml document" do
|
30
30
|
ContainerTest.xml_template.to_xml.should == "<?xml version=\"1.0\"?>\n"
|
31
31
|
end
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
describe "#from_xml" do
|
35
35
|
it "should accept a String, parse it and store it in .ng_xml" do
|
36
36
|
Nokogiri::XML::Document.expects(:parse).returns("parsed xml")
|
@@ -53,36 +53,36 @@ describe "OM::XML::Container" do
|
|
53
53
|
ContainerTest.from_xml.ng_xml.should == "fake template"
|
54
54
|
end
|
55
55
|
end
|
56
|
-
|
56
|
+
|
57
57
|
describe ".to_xml" do
|
58
58
|
it "should call .ng_xml.to_xml" do
|
59
59
|
@container.ng_xml.expects(:to_xml).returns("ng xml")
|
60
60
|
@container.to_xml.should == "ng xml"
|
61
61
|
end
|
62
|
-
|
62
|
+
|
63
63
|
it 'should accept an optional Nokogiri::XML Document as an argument and insert its fields into that (mocked test)' do
|
64
64
|
doc = Nokogiri::XML::Document.parse("<test_xml/>")
|
65
65
|
mock_new_node = mock("new node")
|
66
66
|
doc.root.expects(:add_child).with(@container.ng_xml.root).returns(mock_new_node)
|
67
67
|
result = @container.to_xml(doc)
|
68
68
|
end
|
69
|
-
|
69
|
+
|
70
70
|
it 'should accept an optional Nokogiri::XML Document as an argument and insert its fields into that (functional test)' do
|
71
71
|
doc = Nokogiri::XML::Document.parse("<test_xml/>")
|
72
72
|
@container.to_xml(doc).should == "<?xml version=\"1.0\"?>\n<test_xml>\n <foo>\n <bar>1</bar>\n </foo>\n</test_xml>\n"
|
73
73
|
end
|
74
|
-
|
74
|
+
|
75
75
|
it 'should add to root of Nokogiri::XML::Documents, but add directly to the elements if a Nokogiri::XML::Node is passed in' do
|
76
76
|
mock_new_node = mock("new node")
|
77
77
|
mock_new_node.stubs(:to_xml).returns("foo")
|
78
|
-
|
78
|
+
|
79
79
|
doc = Nokogiri::XML::Document.parse("<test_document/>")
|
80
80
|
el = Nokogiri::XML::Node.new("test_element", Nokogiri::XML::Document.new)
|
81
81
|
doc.root.expects(:add_child).with(@container.ng_xml.root).returns(mock_new_node)
|
82
82
|
el.expects(:add_child).with(@container.ng_xml.root).returns(mock_new_node)
|
83
|
-
@container.to_xml(doc).should
|
83
|
+
@container.to_xml(doc).should
|
84
84
|
@container.to_xml(el)
|
85
85
|
end
|
86
86
|
end
|
87
|
-
|
87
|
+
|
88
88
|
end
|
data/lib/om.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
require '
|
2
|
+
require 'active_support/concern'
|
3
|
+
require 'active_model/dirty'
|
3
4
|
require 'deprecation'
|
4
5
|
require 'nokogiri'
|
5
6
|
|
@@ -9,7 +10,7 @@ module OM
|
|
9
10
|
# Converts [{":person"=>"0"}, ":last_name"] to [{:person=>0}, :last_name]
|
10
11
|
def self.destringify(params)
|
11
12
|
case params
|
12
|
-
when String
|
13
|
+
when String
|
13
14
|
if params == "0" || params.to_i != 0
|
14
15
|
result = params.to_i
|
15
16
|
elsif params[0,1] == ":"
|
@@ -18,13 +19,13 @@ module OM
|
|
18
19
|
result = params.to_sym
|
19
20
|
end
|
20
21
|
return result
|
21
|
-
when Hash
|
22
|
+
when Hash
|
22
23
|
result = {}
|
23
24
|
params.each_pair do |k,v|
|
24
25
|
result[ destringify(k) ] = destringify(v)
|
25
26
|
end
|
26
27
|
return result
|
27
|
-
when Array
|
28
|
+
when Array
|
28
29
|
result = []
|
29
30
|
params.each do |x|
|
30
31
|
result << destringify(x)
|
@@ -34,29 +35,31 @@ module OM
|
|
34
35
|
return params
|
35
36
|
end
|
36
37
|
end
|
37
|
-
|
38
|
+
|
38
39
|
# Convert a Term pointer into a flat array without Hashes.
|
39
40
|
# If include_indices is set to false, node indices will be removed.
|
40
41
|
#
|
41
42
|
# @param [Array] pointers array that you would pass into other Accessor methods
|
42
43
|
# @param [Boolean] include_indices (default: true) if set to false, parent indices will be excluded from the array
|
43
44
|
# @example Turn a pointer into a flat array with node indices preserved
|
44
|
-
# OM.pointers_to_flat_array( [{:conference=>0}, {:role=>1}, :text] )
|
45
|
+
# OM.pointers_to_flat_array( [{:conference=>0}, {:role=>1}, :text] )
|
45
46
|
# => [:conference, 0, :role, 1, :text]
|
46
47
|
# @example Remove node indices by setting include_indices to false
|
47
|
-
# OM.pointers_to_flat_array( [{:conference=>0}, {:role=>1}, :text], false )
|
48
|
+
# OM.pointers_to_flat_array( [{:conference=>0}, {:role=>1}, :text], false )
|
48
49
|
# => [:conference, :role, :text]
|
49
50
|
def self.pointers_to_flat_array(pointers, include_indices=true)
|
50
51
|
flat_array = []
|
51
52
|
pointers.each do |pointer|
|
52
53
|
if pointer.kind_of?(Hash)
|
53
54
|
flat_array << pointer.keys.first
|
54
|
-
|
55
|
+
if include_indices
|
56
|
+
flat_array << pointer.values.first
|
57
|
+
end
|
55
58
|
else
|
56
59
|
flat_array << pointer
|
57
60
|
end
|
58
61
|
end
|
59
|
-
flat_array
|
62
|
+
return flat_array
|
60
63
|
end
|
61
64
|
|
62
65
|
def self.version
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class OM::Samples::ModsArticle
|
2
|
-
|
2
|
+
|
3
3
|
include OM::XML::Document
|
4
|
-
|
4
|
+
|
5
5
|
set_terminology do |t|
|
6
6
|
t.root(:path=>"mods", :xmlns=>"http://www.loc.gov/mods/v3", :schema=>"http://www.loc.gov/standards/mods/v3/mods-3-2.xsd", "xmlns:foo"=>"http://my.custom.namespace")
|
7
7
|
|
@@ -11,17 +11,17 @@ class OM::Samples::ModsArticle
|
|
11
11
|
t.main_title_lang(:path=>{:attribute=> "xml:lang"})
|
12
12
|
}
|
13
13
|
t.french_title(:ref=>[:title_info,:main_title], :attributes=>{"xml:lang"=>"fre"})
|
14
|
-
|
14
|
+
|
15
15
|
t.language(:index_as=>[:facetable],:path=>{:attribute=>"lang"})
|
16
|
-
}
|
16
|
+
}
|
17
17
|
t.language{
|
18
18
|
t.lang_code(:index_as=>[:facetable], :path=>"languageTerm", :attributes=>{:type=>"code"})
|
19
19
|
}
|
20
|
-
t.abstract
|
20
|
+
t.abstract
|
21
21
|
t.subject {
|
22
22
|
t.topic(:index_as=>[:facetable])
|
23
|
-
}
|
24
|
-
t.topic_tag(:proxy=>[:subject, :topic])
|
23
|
+
}
|
24
|
+
t.topic_tag(:proxy=>[:subject, :topic])
|
25
25
|
# t.topic_tag(:index_as=>[:facetable],:path=>"subject", :default_content_path=>"topic")
|
26
26
|
# This is a mods:name. The underscore is purely to avoid namespace conflicts.
|
27
27
|
t.name_ {
|
@@ -40,7 +40,7 @@ class OM::Samples::ModsArticle
|
|
40
40
|
t.computing_id
|
41
41
|
t.name_content(:path=>"text()")
|
42
42
|
}
|
43
|
-
# lookup :person, :first_name
|
43
|
+
# lookup :person, :first_name
|
44
44
|
t.person(:ref=>:name, :attributes=>{:type=>"personal"}, :index_as=>[:facetable])
|
45
45
|
t.department(:proxy=>[:person,:description],:index_as=>[:facetable])
|
46
46
|
t.organization(:ref=>:name, :attributes=>{:type=>"corporate"}, :index_as=>[:facetable])
|
@@ -78,7 +78,7 @@ class OM::Samples::ModsArticle
|
|
78
78
|
t.title(:proxy=>[:title_info, :main_title])
|
79
79
|
t.journal_title(:proxy=>[:journal, :title_info, :main_title])
|
80
80
|
end
|
81
|
-
|
81
|
+
|
82
82
|
# Changes from OM::Properties implementation
|
83
83
|
# renamed family_name => last_name
|
84
84
|
# start_page & end_page now accessible as [:journal, :issue, :pages, :start] (etc.)
|
data/lib/om/tree_node.rb
CHANGED
@@ -1,23 +1,23 @@
|
|
1
1
|
module OM::TreeNode
|
2
|
-
|
2
|
+
|
3
3
|
attr_accessor :ancestors
|
4
|
-
|
4
|
+
|
5
5
|
# insert the mapper into the given parent
|
6
6
|
def set_parent(parent_mapper)
|
7
7
|
parent_mapper.children[@name] = self
|
8
8
|
@ancestors << parent_mapper
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
# insert the given mapper into the current mappers children
|
12
12
|
def add_child(child_mapper)
|
13
13
|
child_mapper.ancestors << self
|
14
|
-
@children[child_mapper.name.to_sym] = child_mapper
|
14
|
+
@children[child_mapper.name.to_sym] = child_mapper
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
def retrieve_child(child_name)
|
18
18
|
child = @children.fetch(child_name, nil)
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
def parent
|
22
22
|
ancestors.last
|
23
23
|
end
|
data/lib/om/version.rb
CHANGED
data/lib/om/xml.rb
CHANGED
@@ -1,56 +1,58 @@
|
|
1
|
-
require
|
2
|
-
require "om/xml/validation"
|
3
|
-
|
4
|
-
require "om/xml/terminology"
|
5
|
-
require "om/xml/term"
|
6
|
-
require "om/xml/term_xpath_generator"
|
7
|
-
require "om/xml/node_generator"
|
8
|
-
require "om/xml/term_value_operators"
|
9
|
-
require "om/xml/named_term_proxy"
|
10
|
-
require "om/xml/document"
|
11
|
-
require "om/xml/dynamic_node"
|
12
|
-
|
13
|
-
require "om/xml/template_registry"
|
14
|
-
|
1
|
+
require 'active_support'
|
15
2
|
module OM::XML
|
3
|
+
extend ActiveSupport::Autoload
|
4
|
+
autoload :Container
|
5
|
+
autoload :Validation
|
6
|
+
autoload :Terminology
|
7
|
+
autoload :Term
|
8
|
+
autoload :TerminologyBasedSolrizer
|
9
|
+
autoload :TermXpathGenerator
|
10
|
+
autoload :NodeGenerator
|
11
|
+
autoload :TermValueOperators
|
12
|
+
autoload :NamedTermProxy
|
13
|
+
autoload :Document
|
14
|
+
autoload :DynamicNode
|
15
|
+
autoload :TemplateRegistry
|
16
16
|
|
17
17
|
# Raised when the XML document or XML template can't be found during an operation
|
18
18
|
class TemplateMissingException < StandardError; end
|
19
|
-
|
19
|
+
|
20
20
|
attr_accessor :ng_xml
|
21
|
-
|
21
|
+
|
22
22
|
# Module Methods -- These methods can be called directly on the Module itself
|
23
|
-
|
23
|
+
|
24
24
|
# Transforms an array of values into a string delimited by +delimiter+
|
25
25
|
def self.delimited_list( values_array, delimiter=", ")
|
26
26
|
values_array.join(delimiter)
|
27
27
|
end
|
28
|
-
|
29
|
-
# Class Methods -- These methods will be available on classes that include this Module
|
30
|
-
|
28
|
+
|
29
|
+
# Class Methods -- These methods will be available on classes that include this Module
|
30
|
+
|
31
31
|
module ClassMethods
|
32
|
-
|
32
|
+
|
33
33
|
# @pointer accessor or property info pointer
|
34
|
-
#
|
34
|
+
#
|
35
35
|
# ex. [[:person,1],:role] will be converted to [{:person=>1},:role]
|
36
|
-
def sanitize_pointer(pointer)
|
37
|
-
if pointer.kind_of?(Array)
|
36
|
+
def sanitize_pointer(pointer)
|
37
|
+
if pointer.kind_of?(Array)
|
38
38
|
pointer.each do |x|
|
39
|
-
|
39
|
+
if x.kind_of?(Array)
|
40
|
+
pointer[pointer.index(x)] = Hash[x[0],x[1]]
|
41
|
+
end
|
40
42
|
end
|
41
43
|
end
|
42
|
-
pointer
|
44
|
+
return pointer
|
43
45
|
end
|
44
|
-
|
46
|
+
|
45
47
|
end
|
46
|
-
|
48
|
+
|
47
49
|
# Instance Methods -- These methods will be available on instances of classes that include this module
|
48
|
-
|
50
|
+
|
49
51
|
def self.included(klass)
|
50
52
|
klass.extend(ClassMethods)
|
51
53
|
klass.send(:include, OM::XML::Container)
|
52
54
|
klass.send(:include, OM::XML::Validation)
|
53
55
|
end
|
54
|
-
|
55
|
-
|
56
|
+
|
57
|
+
|
56
58
|
end
|
data/lib/om/xml/container.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
module OM::XML::Container
|
2
2
|
extend ActiveSupport::Concern
|
3
|
-
|
3
|
+
|
4
4
|
attr_accessor :ng_xml
|
5
|
-
|
6
|
-
# Class Methods -- These methods will be available on classes that include this Module
|
7
|
-
|
5
|
+
|
6
|
+
# Class Methods -- These methods will be available on classes that include this Module
|
7
|
+
|
8
8
|
module ClassMethods
|
9
|
-
|
9
|
+
|
10
10
|
# @xml String, File or Nokogiri::XML::Node
|
11
11
|
# @tmpl ActiveFedora::MetadataDatastream
|
12
12
|
# Careful! If you call this from a constructor, be sure to provide something 'ie. self' as the @tmpl. Otherwise, you will get an infinite loop!
|
@@ -18,25 +18,25 @@ module OM::XML::Container
|
|
18
18
|
else
|
19
19
|
tmpl.ng_xml = Nokogiri::XML::Document.parse(xml)
|
20
20
|
end
|
21
|
-
tmpl
|
21
|
+
return tmpl
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
# By default, new OM Document instances will create an empty xml document, but if you override self.xml_template to return a different object (e.g. Nokogiri::XML::Document), that will be created instead.
|
25
25
|
# You can make this method create the documents however you want as long as it returns a Nokogiri::XML::Document.
|
26
|
-
# In the tutorials, we use Nokogiri::XML::Builder in this mehtod and call its .doc method at the end of xml_template in order to return the Nokogiri::XML::Document object. Instead of using Nokogiri::XML::Builder, you could put your template into an actual xml file and have xml_template use Nokogiri::XML::Document.parse to load it. That’s up to you.
|
26
|
+
# In the tutorials, we use Nokogiri::XML::Builder in this mehtod and call its .doc method at the end of xml_template in order to return the Nokogiri::XML::Document object. Instead of using Nokogiri::XML::Builder, you could put your template into an actual xml file and have xml_template use Nokogiri::XML::Document.parse to load it. That’s up to you.
|
27
27
|
# @return Nokogiri::XML::Document
|
28
28
|
def xml_template
|
29
29
|
Nokogiri::XML::Document.parse("")
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
def ng_xml
|
35
35
|
@ng_xml ||= self.class.xml_template
|
36
36
|
end
|
37
37
|
|
38
38
|
# Instance Methods -- These methods will be available on instances of classes that include this module
|
39
|
-
|
39
|
+
|
40
40
|
def to_xml(xml = ng_xml)
|
41
41
|
if xml == ng_xml
|
42
42
|
return xml.to_xml
|
@@ -52,5 +52,5 @@ module OM::XML::Container
|
|
52
52
|
raise "You can only pass instances of Nokogiri::XML::Node into this method. You passed in #{xml}"
|
53
53
|
end
|
54
54
|
end
|
55
|
-
|
55
|
+
|
56
56
|
end
|
data/lib/om/xml/document.rb
CHANGED
@@ -35,7 +35,7 @@ module OM::XML::Document
|
|
35
35
|
self.terminology_builder.extend_terminology(&block)
|
36
36
|
rebuild_terminology!
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
# (Explicitly) inherit terminology from upstream classes
|
40
40
|
def use_terminology klass
|
41
41
|
self.terminology_builder = klass.terminology_builder.dup
|
@@ -69,8 +69,6 @@ module OM::XML::Document
|
|
69
69
|
end
|
70
70
|
|
71
71
|
def ng_xml_will_change!
|
72
|
-
self.dirty = true if self.respond_to?(:dirty=)
|
73
|
-
|
74
72
|
# throw away older version.
|
75
73
|
changed_attributes['ng_xml'] = nil
|
76
74
|
end
|
@@ -79,23 +77,24 @@ module OM::XML::Document
|
|
79
77
|
changed.include?('ng_xml')
|
80
78
|
end
|
81
79
|
|
82
|
-
def method_missing(
|
83
|
-
if matches = /([^=]
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
super
|
91
|
-
end
|
92
|
-
else
|
80
|
+
def method_missing(method_name, *args)
|
81
|
+
if matches = /([^=]+)=$/.match(method_name.to_s)
|
82
|
+
name = matches[1].to_sym
|
83
|
+
end
|
84
|
+
|
85
|
+
name ||= method_name
|
86
|
+
|
87
|
+
begin
|
93
88
|
term = self.class.terminology.retrieve_term(name)
|
94
|
-
|
95
|
-
|
89
|
+
|
90
|
+
if /=$/.match(method_name.to_s)
|
91
|
+
node = OM::XML::DynamicNode.new(name, nil, self, term)
|
92
|
+
return node.val=args
|
96
93
|
else
|
97
|
-
|
94
|
+
return OM::XML::DynamicNode.new(name, args.first, self, term)
|
98
95
|
end
|
96
|
+
rescue OM::XML::Terminology::BadPointerError
|
97
|
+
super
|
99
98
|
end
|
100
99
|
end
|
101
100
|
|
@@ -194,7 +193,9 @@ module OM::XML::Document
|
|
194
193
|
|
195
194
|
private
|
196
195
|
def manipulate_node(method, target, *args, &block)
|
197
|
-
|
196
|
+
if target.is_a?(Array)
|
197
|
+
target = self.find_by_terms(*target)
|
198
|
+
end
|
198
199
|
raise "You must call define_template before calling #{method}" if template_registry.nil?
|
199
200
|
ng_xml_will_change!
|
200
201
|
template_registry.send(method, target, *args, &block)
|