checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1de731732be29cdf0c460beebcb5b603deccb18c
4
+ data.tar.gz: 6fa913f9d7bcdd57e7d29555a266d265dd426ad0
5
+ SHA512:
6
+ metadata.gz: e947f9c90119f8ac601105505d947a2ad78d4307ada79f3f7e609fd64ecb71c0330bbe668438e1d4ee71aac4dbcf112a9f5d2a0fe4a841d9a22125b81cd78e9d
7
+ data.tar.gz: 4db6a2f387c9630f6e9909966bc81e9939110ac92b6588745fb82766ec23d3249041ddbe70b5ddba6322b094622e51cdd09da26365bec6c6af7fcb12cc2a9f5a
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,113 @@
1
+ # How to Contribute
2
+
3
+ We want your help to make Project Hydra great.
4
+ There are a few guidelines that we need contributors to follow so that we can have a chance of keeping on top of things.
5
+
6
+ ## Hydra Project Intellectual Property Licensing and Ownership
7
+
8
+ All code contributors must have an Individual Contributor License Agreement (iCLA) on file with the Hydra Project Steering Group.
9
+ If the contributor works for an institution, the institution must have a Corporate Contributor License Agreement (cCLA) on file.
10
+
11
+ https://wiki.duraspace.org/display/hydra/Hydra+Project+Intellectual+Property+Licensing+and+Ownership
12
+
13
+ You should also add yourself to the `CONTRIBUTORS.md` file in the root of the project.
14
+
15
+ ## Contribution Tasks
16
+
17
+ * Reporting Issues
18
+ * Making Changes
19
+ * Submitting Changes
20
+ * Merging Changes
21
+
22
+ ### Reporting Issues
23
+
24
+ * Make sure you have a [GitHub account](https://github.com/signup/free)
25
+ * Submit a [Github issue](./issues) by:
26
+ * Clearly describing the issue
27
+ * Provide a descriptive summary
28
+ * Explain the expected behavior
29
+ * Explain the actual behavior
30
+ * Provide steps to reproduce the actual behavior
31
+
32
+ ### Making Changes
33
+
34
+ * Fork the repository on GitHub
35
+ * Create a topic branch from where you want to base your work.
36
+ * This is usually the master branch.
37
+ * To quickly create a topic branch based on master; `git branch fix/master/my_contribution master`
38
+ * Then checkout the new branch with `git checkout fix/master/my_contribution`.
39
+ * Please avoid working directly on the `master` branch.
40
+ * You may find the [hub suite of commands](https://github.com/defunkt/hub) helpful
41
+ * Make commits of logical units.
42
+ * Your commit should include a high level description of your work in HISTORY.textile
43
+ * Check for unnecessary whitespace with `git diff --check` before committing.
44
+ * Make sure your commit messages are [well formed](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
45
+ * If you created an issue, you can close it by including "Closes #issue" in your commit message. See [Github's blog post for more details](https://github.com/blog/1386-closing-issues-via-commit-messages)
46
+
47
+ ```
48
+ Present tense short summary (50 characters or less)
49
+
50
+ More detailed description, if necessary. It should be wrapped to 72
51
+ characters. Try to be as descriptive as you can, even if you think that
52
+ the commit content is obvious, it may not be obvious to others. You
53
+ should add such description also if it's already present in bug tracker,
54
+ it should not be necessary to visit a webpage to check the history.
55
+
56
+ Include Closes #<issue-number> when relavent.
57
+
58
+ Description can have multiple paragraphs and you can use code examples
59
+ inside, just indent it with 4 spaces:
60
+
61
+ class PostsController
62
+ def index
63
+ respond_with Post.limit(10)
64
+ end
65
+ end
66
+
67
+ You can also add bullet points:
68
+
69
+ - you can use dashes or asterisks
70
+
71
+ - also, try to indent next line of a point for readability, if it's too
72
+ long to fit in 72 characters
73
+ ```
74
+
75
+ * Make sure you have added the necessary tests for your changes.
76
+ * Run _all_ the tests to assure nothing else was accidentally broken.
77
+ * When you are ready to submit a pull request
78
+
79
+ ### Submitting Changes
80
+
81
+ [Detailed Walkthrough of One Pull Request per Commit](http://ndlib.github.io/practices/one-commit-per-pull-request/)
82
+
83
+ * Read the article ["Using Pull Requests"](https://help.github.com/articles/using-pull-requests) on GitHub.
84
+ * Make sure your branch is up to date with its parent branch (i.e. master)
85
+ * `git checkout master`
86
+ * `git pull --rebase`
87
+ * `git checkout <your-branch>`
88
+ * `git rebase master`
89
+ * It is likely a good idea to run your tests again.
90
+ * Squash the commits for your branch into one commit
91
+ * `git rebase --interactive HEAD~<number-of-commits>` ([See Github help](https://help.github.com/articles/interactive-rebase))
92
+ * To determine the number of commits on your branch: `git log master..<your-branch> --oneline | wc -l`
93
+ * Squashing your branch's changes into one commit is "good form" and helps the person merging your request to see everything that is going on.
94
+ * Push your changes to a topic branch in your fork of the repository.
95
+ * Submit a pull request from your fork to the project.
96
+
97
+ ### Merging Changes
98
+
99
+ * It is considered "poor from" to merge your own request.
100
+ * Please take the time to review the changes and get a sense of what is being changed. Things to consider:
101
+ * Does the commit message explain what is going on?
102
+ * Does the code changes have tests? _Not all changes need new tests, some changes are refactorings_
103
+ * Does the commit contain more than it should? Are two separate concerns being addressed in one commit?
104
+ * Did the Travis tests complete successfully?
105
+ * If you are uncertain, bring other contributors into the conversation by creating a comment that includes their @username.
106
+ * If you like the pull request, but want others to chime in, create a +1 comment and tag a user.
107
+
108
+ # Additional Resources
109
+
110
+ * [General GitHub documentation](http://help.github.com/)
111
+ * [GitHub pull request documentation](http://help.github.com/send-pull-requests/)
112
+ * [Pro Git](http://git-scm.com/book) is both a free and excellent book about Git.
113
+ * [A Git Config for Contributing](http://ndlib.github.io/practices/my-typical-per-project-git-config/)
data/History.textile CHANGED
@@ -1,9 +1,3 @@
1
- h3. 3.0.3 (19 Jul 2013)
2
- Fix overly-aggressive template inheritance bug introduced in 3.0.2
3
-
4
- h3. 3.0.2 (15 Jul 2013)
5
- Add terminology and template inheritance
6
-
7
1
h3. 3.0.1 (25 Jun 2013)
8
2
Fix bug where values that were the same as the existing values were
9
3
removed from the update list
data/README.md ADDED
@@ -0,0 +1,41 @@
1
+ [![Build Status](https://travis-ci.org/projecthydra/om.png?branch=master)](https://travis-ci.org/projecthydra/om)
2
+ [![Gem Version](https://badge.fury.io/rb/om.png)](http://badge.fury.io/rb/om)
3
+
4
+ # om (Opinionated Metadata)
5
+
6
+ A library to help you tame sprawling XML schemas like MODS.
7
+
8
+ OM allows you to define a "terminology" to ease translation between XML and ruby objects – you can query the xml for Nodes or node values without ever writing a line of XPath.
9
+
10
+ OM "terms" are ruby symbols you define (in the terminology) that map specific XML content into ruby object attributes.
11
+
12
+ ## Tutorials & Reference
13
+
14
+ * [Tame Your XML with OM](https://github.com/projecthydra/om/wiki/Tame-your-XML-with-OM)
15
+ * [Common OM Patterns](https://github.com/projecthydra/om/blob/master/COMMON_OM_PATTERNS.textile)
16
+
17
+ ### Solrizing Documents
18
+
19
+ The solrizer gem provides support for indexing XML documents into Solr based on OM Terminologies.
20
+ That process is documented in the [solrizer README](https://github.com/projecthydra/solrizer)
21
+
22
+ ## OM in the Wild
23
+
24
+ We have a page on the Hydra wiki with a list of OM Terminologies in active use:
25
+ [OM Terminologies in the Wild](https://wiki.duraspace.org/display/hydra/OM+Terminologies+in+the+Wild)
26
+
27
+ ## Acknowledgments
28
+
29
+ ### Creator
30
+
31
+ Matt Zumwalt ([MediaShelf](http://yourmediashelf.com)
32
+
33
+ ### Thanks To
34
+
35
+ * Bess Sadler, who enabled us to take knowledge gleaned from developing Blacklight and apply it to OM metadata indexing
36
+ * Ross Singer
37
+ * Those who participated in the Opinionated MODS breakout session at Code4Lib 2010
38
+
39
+ ## Copyright
40
+
41
+ Copyright (c) 2010 Matt Zumwalt. See LICENSE for details.
data/README.textile DELETED
@@ -1,36 +0,0 @@
1
- !https://travis-ci.org/projecthydra/om.png!:https://travis-ci.org/projecthydra/om
2
-
3
- h1. om (Optinionated Metadata)
4
-
5
- A library to help you tame sprawling XML schemas like MODS.
6
-
7
- OM allows you to define a “terminology” to ease translation between XML and ruby objects – you can query the xml for Nodes or node values without ever writing a line of XPath.
8
-
9
- OM “terms” are ruby symbols you define (in the terminology) that map specific XML content into ruby object attributes.
10
-
11
- h2. Tutorials & Reference
12
-
13
- * "Tame Your XML with OM":https://github.com/projecthydra/om/wiki/Tame-your-XML-with-OM
14
- * "Common OM Patterns":https://github.com/projecthydra/om/blob/master/COMMON_OM_PATTERNS.textile
15
-
16
- h3. Solrizing Documents
17
-
18
- The solrizer gem provides support for indexing XML documents into Solr based on OM Terminologies. That process is documented in the "solrizer documentation":http://rdoc.info/github/projecthydra/solrizer
19
-
20
- h2. OM in the Wild
21
-
22
- We have a page on the Hydra wiki with a list of OM Terminologies in active use: "OM Terminologies in the Wild":https://wiki.duraspace.org/display/hydra/OM+Terminologies+in+the+Wild
23
-
24
- h2. Acknowledgements
25
-
26
- Creator: Matt Zumwalt ("MediaShelf":http://yourmediashelf.com)
27
-
28
- Thanks to
29
-
30
- Bess Sadler, who enabled us to take knowledge gleaned from developing Blacklight and apply it to OM metadata indexing
31
- Ross Singer
32
- Those who participated in the Opinionated MODS breakout session at Code4Lib 2010
33
-
34
- h2. Copyright
35
-
36
- Copyright (c) 2010 Matt Zumwalt. See LICENSE for details.
data/gemfiles/gemfile.rails4 CHANGED
@@ -2,7 +2,7 @@ source "http://rubygems.org"
2
2
3
3
gemspec :path=>"../"
4
4
5
- gem 'activemodel', '4.0.0.rc1'
5
+ gem 'activemodel', '~> 4.0.0'
6
6
7
7
group :development, :test do
8
8
gem 'simplecov', :platform => :mri_19
data/lib/om.rb CHANGED
@@ -65,6 +65,8 @@ module OM
65
65
def self.version
66
66
Om::VERSION
67
67
end
68
+
69
+ class TypeMismatch < StandardError; end
68
70
end
69
71
70
72
module OM::XML; end
data/lib/om/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
module Om
2
- VERSION = "3.0.3"
2
+ VERSION = "3.0.5"
3
3
end
data/lib/om/xml/document.rb CHANGED
@@ -24,7 +24,12 @@ module OM::XML::Document
24
24
end
25
25
26
26
def terminology_builder
27
- @terminology_builder ||= OM::XML::Terminology::Builder.new
27
+ return @terminology_builder if @terminology_builder
28
+ @terminology_builder = if superclass.respond_to? :terminology_builder
29
+ superclass.terminology_builder.dup
30
+ else
31
+ OM::XML::Terminology::Builder.new
32
+ end
28
33
end
29
34
30
35
def template_registry
data/lib/om/xml/dynamic_node.rb CHANGED
@@ -44,7 +44,7 @@ module OM
44
44
elsif args.length > 1
45
45
new_update_node_with_index(name, args)
46
46
else
47
- child = term_child_by_name(term.nil? ? parent.term : term, name)
47
+ child = term_child_by_name(term.nil? ? parent.term : term, name)
48
48
if child
49
49
OM::XML::DynamicNode.new(name, args.first, @document, child, self)
50
50
else
@@ -53,6 +53,10 @@ module OM
53
53
end
54
54
end
55
55
56
+ def respond_to?(method)
57
+ super || val.respond_to?(method)
58
+ end
59
+
56
60
def new_update_node(name, args)
57
61
modified_name = name.to_s.chop.to_sym
58
62
child = term.retrieve_term(modified_name)
@@ -97,6 +101,8 @@ module OM
97
101
end
98
102
end
99
103
104
+ # This resolves the target of this dynamic node into a reified Array
105
+ # @return [Array]
100
106
def val
101
107
query = xpath
102
108
trim_text = !query.index("text()").nil?
@@ -119,7 +125,11 @@ module OM
119
125
end
120
126
121
127
def ==(other)
122
- val == other
128
+ other == val
129
+ end
130
+
131
+ def !=(other)
132
+ val != other
123
133
end
124
134
125
135
def eql?(other)
data/lib/om/xml/term.rb CHANGED
@@ -4,288 +4,291 @@ require 'om/xml/term_builder'
4
4
# type, index_as, attributes,
5
5
# is_root_term, required
6
6
#
7
- class OM::XML::Term
7
+ module OM
8
+ class XML::Term
8
9
9
- include OM::TreeNode
10
- include OM::XML::TermBuilder
10
+ include TreeNode
11
+ include XML::TermBuilder
11
12
12
- attr_accessor :name, :xpath, :xpath_constrained, :xpath_relative, :path, :index_as, :required, :type, :variant_of, :path, :default_content_path, :is_root_term
13
- attr_accessor :children, :internal_xml, :terminology
13
+ attr_accessor :name, :xpath, :xpath_constrained, :xpath_relative, :path, :index_as, :required, :type, :variant_of, :path, :default_content_path, :is_root_term
14
+ attr_accessor :children, :internal_xml, :terminology
14
15
15
- # Any XML attributes that qualify the Term.
16
- #
17
- # @example Declare a Term that has a given attribute (ie. //title[@xml:lang='eng'])
18
- # t.english_title(:path=>"title", :attributes=>{"xml:lang"=>"eng"}
19
- # @example Use nil to point to nodes that do not have a given attribute (ie. //title[not(@xml:lang)])
20
- # t.title_without_lang_attribute(:path=>"title", :attributes=>{"xml:lang"=>nil})
21
- attr_accessor :attributes
16
+ # Any XML attributes that qualify the Term.
17
+ #
18
+ # @example Declare a Term that has a given attribute (ie. //title[@xml:lang='eng'])
19
+ # t.english_title(:path=>"title", :attributes=>{"xml:lang"=>"eng"}
20
+ # @example Use nil to point to nodes that do not have a given attribute (ie. //title[not(@xml:lang)])
21
+ # t.title_without_lang_attribute(:path=>"title", :attributes=>{"xml:lang"=>nil})
22
+ attr_accessor :attributes
22
23
23
- # Namespace Prefix (xmlns) for the Term.
24
- #
25
- # By default, OM assumes that all terms in a Terminology have the namespace set in the root of the document. If you want to set a different namespace for a Term, pass :namespace_prefix into its initializer (or call .namespace_prefix= on its builder)
26
- # If a node has _no_ namespace, you must explicitly set namespace_prefix to nil. Currently you have to do this on _each_ term, you can't set namespace_prefix to nil for an entire Terminology.
27
- #
28
- # @example
29
- # # For xml like this
30
- # <foo xmlns="http://foo.com/schemas/fooschema" xmlns:bar="http://bar.com/schemas/barschema">
31
- # <address>1400 Pennsylvania Avenue</address>
32
- # <bar:latitude>56</bar:latitude>
33
- # </foo>
34
- #
35
- # # The Terminology would look like this
36
- # OM::XML::Terminology::Builder.new do |t|
37
- # t.root(:name=>:foo, :path=>"foo", :xmlns=>"http://foo.com/schemas/fooschema", "xmlns:bar"=>"http://bar.com/schemas/barschema")
38
- # t.address
39
- # t.latitude(:namespace_prefix=>"bar")
40
- # end
41
- #
42
- attr_accessor :namespace_prefix
24
+ # Namespace Prefix (xmlns) for the Term.
25
+ #
26
+ # By default, OM assumes that all terms in a Terminology have the namespace set in the root of the document. If you want to set a different namespace for a Term, pass :namespace_prefix into its initializer (or call .namespace_prefix= on its builder)
27
+ # If a node has _no_ namespace, you must explicitly set namespace_prefix to nil. Currently you have to do this on _each_ term, you can't set namespace_prefix to nil for an entire Terminology.
28
+ #
29
+ # @example
30
+ # # For xml like this
31
+ # <foo xmlns="http://foo.com/schemas/fooschema" xmlns:bar="http://bar.com/schemas/barschema">
32
+ # <address>1400 Pennsylvania Avenue</address>
33
+ # <bar:latitude>56</bar:latitude>
34
+ # </foo>
35
+ #
36
+ # # The Terminology would look like this
37
+ # OM::XML::Terminology::Builder.new do |t|
38
+ # t.root(:name=>:foo, :path=>"foo", :xmlns=>"http://foo.com/schemas/fooschema", "xmlns:bar"=>"http://bar.com/schemas/barschema")
39
+ # t.address
40
+ # t.latitude(:namespace_prefix=>"bar")
41
+ # end
42
+ #
43
+ attr_accessor :namespace_prefix
43
44
44
45
45
- # h2. Namespaces
46
- # By default, OM assumes you have no namespace defined unless it is explicitly defined at the root of your document.
47
- #
48
- # @param [Symbol] name the name to refer to this term by
49
- # @param [Hash] opts
50
- # @option opts [Array] :index_as a list of indexing hints provided to to_solr
51
- # @option opts [String] :path partial xpath that points to the node.
52
- # @option opts [Hash] :attributes xml attributes to match in the selector
53
- # @option opts [String] :namespace_prefix xml namespace for this node. If not provided, the default namespace set in the terminology will be used.
54
- # @option opts [Symbol] :type one of :string, :date, :time :integer. Defaults to :string
55
- def initialize(name, opts={}, terminology=nil)
56
- opts = {:ancestors=>[], :children=>{}}.merge(opts)
57
- [:children, :ancestors,:path, :index_as, :required, :variant_of, :path, :attributes, :default_content_path, :namespace_prefix].each do |accessor_name|
58
- instance_variable_set("@#{accessor_name}", opts.fetch(accessor_name, nil) )
59
- end
46
+ # h2. Namespaces
47
+ # By default, OM assumes you have no namespace defined unless it is explicitly defined at the root of your document.
48
+ #
49
+ # @param [Symbol] name the name to refer to this term by
50
+ # @param [Hash] opts
51
+ # @option opts [Array] :index_as a list of indexing hints provided to to_solr
52
+ # @option opts [String] :path partial xpath that points to the node.
53
+ # @option opts [Hash] :attributes xml attributes to match in the selector
54
+ # @option opts [String] :namespace_prefix xml namespace for this node. If not provided, the default namespace set in the terminology will be used.
55
+ # @option opts [Symbol] :type one of :string, :date, :time :integer. Defaults to :string
56
+ def initialize(name, opts={}, terminology=nil)
57
+ opts = {:ancestors=>[], :children=>{}}.merge(opts)
58
+ [:children, :ancestors,:path, :index_as, :required, :variant_of, :path, :attributes, :default_content_path, :namespace_prefix].each do |accessor_name|
59
+ instance_variable_set("@#{accessor_name}", opts.fetch(accessor_name, nil) )
60
+ end
60
61
61
- self.type = opts[:type] || :string
62
+ self.type = opts[:type] || :string
62
63
63
- unless terminology.nil?
64
- if opts[:namespace_prefix].nil?
65
- unless terminology.namespaces["xmlns"].nil?
66
- @namespace_prefix = "oxns"
64
+ unless terminology.nil?
65
+ if opts[:namespace_prefix].nil?
66
+ unless terminology.namespaces["xmlns"].nil?
67
+ @namespace_prefix = "oxns"
68
+ end
67
69
end
68
70
end
71
+ @name = name
72
+ if @path.nil? || @path.empty?
73
+ @path = name.to_s
74
+ end
69
75
end
70
- @name = name
71
- if @path.nil? || @path.empty?
72
- @path = name.to_s
73
- end
74
- end
75
76
76
77
77
- def sanitize_new_values(new_values)
78
- # Sanitize new_values to always be a hash with indexes
79
- case new_values
80
- when Hash
81
- sanitize_new_values(new_values.values)
82
- when Array
83
- new_values.map {|v| serialize(v)}
78
+ def sanitize_new_values(new_values)
79
+ # Sanitize new_values to always be a hash with indexes
80
+ case new_values
81
+ when Hash
82
+ sanitize_new_values(new_values.values)
83
+ when Array
84
+ new_values.map {|v| serialize(v)}
85
+ else
86
+ [serialize(new_values)]
87
+ end
88
+ end
89
+
90
+ # @param val [String,Date,Integer]
91
+ def serialize (val)
92
+ return if val.nil?
93
+ case type
94
+ when :date, :integer
95
+ val.to_s
96
+ when :time
97
+ time = val.to_time
98
+ raise TypeMismatch, "Can't convert `#{val}` to time" if time.nil?
99
+ time.utc.iso8601
100
+ when :boolean
101
+ val.to_s
84
102
else
85
- [serialize(new_values)]
103
+ val
86
104
end
87
- end
88
-
89
- # @param val [String,Date,Integer]
90
- def serialize (val)
91
- return if val.nil?
92
- case type
93
- when :date, :integer
94
- val.to_s
95
- when :time
96
- val.to_time.utc.iso8601
97
- when :boolean
98
- val.to_s
99
- else
100
- val
101
105
end
102
- end
103
106
104
- # @param [String] val the value (from xml) to deserialize into the correct object type.
105
- # @return [String,Date,Integer]
106
- def deserialize(val)
107
- case type
108
- when :date
109
- #TODO use present?
110
- val.map { |v| !v.empty? ? Date.parse(v) : nil}
111
- when :time
112
- #TODO use present?
113
- val.map { |v| !v.empty? ? DateTime.parse(v) : nil}
114
- when :integer
115
- #TODO use blank?
116
- val.map { |v| v.empty? ? nil : v.to_i}
117
- when :boolean
118
- val.map { |v| v == 'true' }
119
- else
120
- val
107
+ # @param [String] val the value (from xml) to deserialize into the correct object type.
108
+ # @return [String,Date,Integer]
109
+ def deserialize(val)
110
+ case type
111
+ when :date
112
+ #TODO use present?
113
+ val.map { |v| !v.empty? ? Date.parse(v) : nil}
114
+ when :time
115
+ #TODO use present?
116
+ val.map { |v| !v.empty? ? DateTime.parse(v) : nil}
117
+ when :integer
118
+ #TODO use blank?
119
+ val.map { |v| v.empty? ? nil : v.to_i}
120
+ when :boolean
121
+ val.map { |v| v == 'true' }
122
+ else
123
+ val
124
+ end
121
125
end
122
- end
123
126
124
- def self.from_node(mapper_xml)
125
- name = mapper_xml.attribute("name").text.to_sym
126
- attributes = {}
127
- mapper_xml.xpath("./attribute").each do |a|
128
- attributes[a.attribute("name").text.to_sym] = a.attribute("value").text
127
+ def self.from_node(mapper_xml)
128
+ name = mapper_xml.attribute("name").text.to_sym
129
+ attributes = {}
130
+ mapper_xml.xpath("./attribute").each do |a|
131
+ attributes[a.attribute("name").text.to_sym] = a.attribute("value").text
129
- end
130
- new_mapper = self.new(name, :attributes=>attributes)
131
- [:index_as, :required, :type, :variant_of, :path, :default_content_path, :namespace_prefix].each do |accessor_name|
132
- attribute = mapper_xml.attribute(accessor_name.to_s)
133
- unless attribute.nil?
134
- new_mapper.instance_variable_set("@#{accessor_name}", attribute.text )
135
132
end
136
- end
137
- new_mapper.internal_xml = mapper_xml
133
+ new_mapper = self.new(name, :attributes=>attributes)
134
+ [:index_as, :required, :type, :variant_of, :path, :default_content_path, :namespace_prefix].each do |accessor_name|
135
+ attribute = mapper_xml.attribute(accessor_name.to_s)
136
+ unless attribute.nil?
137
+ new_mapper.instance_variable_set("@#{accessor_name}", attribute.text )
138
+ end
139
+ end
140
+ new_mapper.internal_xml = mapper_xml
138
141
139
- mapper_xml.xpath("./mapper").each do |child_node|
140
- child = self.from_node(child_node)
141
- new_mapper.add_child(child)
142
- end
142
+ mapper_xml.xpath("./mapper").each do |child_node|
143
+ child = self.from_node(child_node)
144
+ new_mapper.add_child(child)
145
+ end
143
146
144
- return new_mapper
145
- end
147
+ return new_mapper
148
+ end
146
149
147
- ##
148
- # Always co-erce :index_as attributes into an Array
149
- def index_as
150
- Array(@index_as)
151
- end
150
+ ##
151
+ # Always co-erce :index_as attributes into an Array
152
+ def index_as
153
+ Array(@index_as)
154
+ end
152
155
153
- # crawl down into mapper's children hash to find the desired mapper
154
- # ie. @test_mapper.retrieve_mapper(:conference, :role, :text)
155
- def retrieve_term(*pointers)
156
- children_hash = self.children
157
- pointers.each do |p|
158
- if children_hash.has_key?(p)
159
- target = children_hash[p]
160
- if pointers.index(p) == pointers.length-1
161
- return target
156
+ # crawl down into mapper's children hash to find the desired mapper
157
+ # ie. @test_mapper.retrieve_mapper(:conference, :role, :text)
158
+ def retrieve_term(*pointers)
159
+ children_hash = self.children
160
+ pointers.each do |p|
161
+ if children_hash.has_key?(p)
162
+ target = children_hash[p]
163
+ if pointers.index(p) == pointers.length-1
164
+ return target
165
+ else
166
+ children_hash = target.children
167
+ end
162
168
else
163
- children_hash = target.children
169
+ return nil
164
170
end
165
- else
166
- return nil
167
171
end
172
+ return target
168
173
end
169
- return target
170
- end
171
174
172
- def is_root_term?
173
- @is_root_term == true
174
- end
175
+ def is_root_term?
176
+ @is_root_term == true
177
+ end
175
178
176
- def xpath_absolute
177
- @xpath
178
- end
179
+ def xpath_absolute
180
+ @xpath
181
+ end
179
182
180
- # +term_pointers+ reference to the property you want to generate a builder template for
181
- # @param [Hash] extra_opts
182
- # @option extra_opts [Hash] :attributes
183
- def xml_builder_template(extra_opts = {})
184
- extra_attributes = extra_opts.fetch(:attributes, {})
183
+ # +term_pointers+ reference to the property you want to generate a builder template for
184
+ # @param [Hash] extra_opts
185
+ # @option extra_opts [Hash] :attributes
186
+ def xml_builder_template(extra_opts = {})
187
+ extra_attributes = extra_opts.fetch(:attributes, {})
185
188
186
- node_options = []
187
- node_child_template = ""
188
- if !self.default_content_path.nil?
189
- node_child_options = ["\':::builder_new_value:::\'"]
190
- node_child_template = " { xml.#{self.default_content_path}( #{OM::XML.delimited_list(node_child_options)} ) }"
191
- else
192
- node_options = ["\':::builder_new_value:::\'"]
193
- end
194
- if !self.attributes.nil?
195
- self.attributes.merge(extra_attributes).each_pair do |k,v|
196
- node_options << "\'#{k}\'=>\'#{v}\'" unless v == :none
189
+ node_options = []
190
+ node_child_template = ""
191
+ if !self.default_content_path.nil?
192
+ node_child_options = ["\':::builder_new_value:::\'"]
193
+ node_child_template = " { xml.#{self.default_content_path}( #{OM::XML.delimited_list(node_child_options)} ) }"
194
+ else
195
+ node_options = ["\':::builder_new_value:::\'"]
196
+ end
197
+ if !self.attributes.nil?
198
+ self.attributes.merge(extra_attributes).each_pair do |k,v|
199
+ node_options << "\'#{k}\'=>\'#{v}\'" unless v == :none
200
+ end
197
201
end
198
- end
199
202
200
- builder_ref = if self.path.include?(":")
201
- "xml['#{self.path[0..path.index(":")-1]}']"
202
- elsif !self.namespace_prefix.nil? and self.namespace_prefix != 'oxns'
203
- "xml['#{self.namespace_prefix}']"
204
- else
205
- "xml"
206
- end
203
+ builder_ref = if self.path.include?(":")
204
+ "xml['#{self.path[0..path.index(":")-1]}']"
205
+ elsif !self.namespace_prefix.nil? and self.namespace_prefix != 'oxns'
206
+ "xml['#{self.namespace_prefix}']"
207
+ else
208
+ "xml"
209
+ end
207
210
208
- attribute = OM::XML.delimited_list(node_options)
211
+ attribute = OM::XML.delimited_list(node_options)
209
212
210
- builder_method = if self.path.include?(":")
211
- "#{self.path[path.index(":")+1..-1]}( #{attribute} )"
212
- elsif self.path.include?(".")
213
- "send(:\\\"#{self.path}\\\", #{attribute} )"
214
- elsif self.path.kind_of?(Hash) && self.path[:attribute]
215
- "@#{self.path[:attribute]}( #{OM::XML.delimited_list(node_options)} )"
216
- elsif Nokogiri::XML::Builder.method_defined? self.path.to_sym
217
- "#{self.path}_( #{OM::XML.delimited_list(node_options)} )"
218
- else
219
- "#{self.path}( #{OM::XML.delimited_list(node_options)} )"
213
+ builder_method = if self.path.include?(":")
214
+ "#{self.path[path.index(":")+1..-1]}( #{attribute} )"
215
+ elsif self.path.include?(".")
216
+ "send(:\\\"#{self.path}\\\", #{attribute} )"
217
+ elsif self.path.kind_of?(Hash) && self.path[:attribute]
218
+ "@#{self.path[:attribute]}( #{OM::XML.delimited_list(node_options)} )"
219
+ elsif Nokogiri::XML::Builder.method_defined? self.path.to_sym
220
+ "#{self.path}_( #{OM::XML.delimited_list(node_options)} )"
221
+ else
222
+ "#{self.path}( #{OM::XML.delimited_list(node_options)} )"
223
+ end
224
+ template = "#{builder_ref}.#{builder_method}#{node_child_template}"
225
+ return template.gsub( /:::(.*?):::/ ) { '#{'+$1+'}' }
220
226
end
221
- template = "#{builder_ref}.#{builder_method}#{node_child_template}"
222
- return template.gsub( /:::(.*?):::/ ) { '#{'+$1+'}' }
223
- end
224
227
225
- # Generates absolute, relative, and constrained xpaths for the term, setting xpath, xpath_relative, and xpath_constrained accordingly.
226
- # Also triggers update_xpath_values! on all child nodes, as their absolute paths rely on those of their parent nodes.
227
- def generate_xpath_queries!
228
- self.xpath = OM::XML::TermXpathGenerator.generate_absolute_xpath(self)
229
- self.xpath_constrained = OM::XML::TermXpathGenerator.generate_constrained_xpath(self)
230
- self.xpath_relative = OM::XML::TermXpathGenerator.generate_relative_xpath(self)
231
- self.children.each_value {|child| child.generate_xpath_queries! }
232
- return self
233
- end
228
+ # Generates absolute, relative, and constrained xpaths for the term, setting xpath, xpath_relative, and xpath_constrained accordingly.
229
+ # Also triggers update_xpath_values! on all child nodes, as their absolute paths rely on those of their parent nodes.
230
+ def generate_xpath_queries!
231
+ self.xpath = OM::XML::TermXpathGenerator.generate_absolute_xpath(self)
232
+ self.xpath_constrained = OM::XML::TermXpathGenerator.generate_constrained_xpath(self)
233
+ self.xpath_relative = OM::XML::TermXpathGenerator.generate_relative_xpath(self)
234
+ self.children.each_value {|child| child.generate_xpath_queries! }
235
+ return self
236
+ end
234
237
235
- # Return an XML representation of the Term
236
- # @param [Hash] options the term will be added to it. If :children=>false, skips rendering child Terms
237
- # @param [Nokogiri::XML::Document] document (optional) document to insert the term xml into
238
- # @return [Nokogiri::XML::Document]
239
- # @example If :children=>false, skips rendering child Terms
240
- # term.to_xml(:children=>false)
241
- # @example You can provide your own Nokogiri document to insert the xml into
242
- # doc = Nokogiri::XML::Document.new
243
- # term.to_xml({}, document=doc)
244
- def to_xml(options={}, document=Nokogiri::XML::Document.new)
245
- builder = Nokogiri::XML::Builder.with(document) do |xml|
246
- xml.term(:name=>name) {
247
- if is_root_term?
248
- xml.is_root_term("true")
249
- end
250
- xml.path path
251
- xml.namespace_prefix namespace_prefix
252
- unless attributes.nil? || attributes.empty?
253
- xml.attributes {
254
- attributes.each_pair do |attribute_name, attribute_value|
255
- xml.send("#{attribute_name}_".to_sym, attribute_value)
238
+ # Return an XML representation of the Term
239
+ # @param [Hash] options the term will be added to it. If :children=>false, skips rendering child Terms
240
+ # @param [Nokogiri::XML::Document] document (optional) document to insert the term xml into
241
+ # @return [Nokogiri::XML::Document]
242
+ # @example If :children=>false, skips rendering child Terms
243
+ # term.to_xml(:children=>false)
244
+ # @example You can provide your own Nokogiri document to insert the xml into
245
+ # doc = Nokogiri::XML::Document.new
246
+ # term.to_xml({}, document=doc)
247
+ def to_xml(options={}, document=Nokogiri::XML::Document.new)
248
+ builder = Nokogiri::XML::Builder.with(document) do |xml|
249
+ xml.term(:name=>name) {
250
+ if is_root_term?
251
+ xml.is_root_term("true")
252
+ end
253
+ xml.path path
254
+ xml.namespace_prefix namespace_prefix
255
+ unless attributes.nil? || attributes.empty?
256
+ xml.attributes {
257
+ attributes.each_pair do |attribute_name, attribute_value|
258
+ xml.send("#{attribute_name}_".to_sym, attribute_value)
259
+ end
260
+ }
261
+ end
262
+ xml.index_as {
263
+ unless index_as.nil?
264
+ index_as.each { |index_type| xml.index_type }
256
265
end
257
266
}
258
- end
259
- xml.index_as {
260
- unless index_as.nil?
261
- index_as.each { |index_type| xml.index_type }
267
+ xml.required required
268
+ xml.data_type type
269
+ unless variant_of.nil?
270
+ xml.variant_of variant_of
271
+ end
272
+ unless default_content_path.nil?
273
+ xml.default_content_path default_content_path
274
+ end
275
+ xml.xpath {
276
+ xml.relative xpath_relative
277
+ xml.absolute xpath
278
+ xml.constrained xpath_constrained
279
+ }
280
+ if options.fetch(:children, true)
281
+ xml.children
262
282
end
263
283
}
264
- xml.required required
265
- xml.data_type type
266
- unless variant_of.nil?
267
- xml.variant_of variant_of
268
- end
269
- unless default_content_path.nil?
284
+ end
285
+ doc = builder.doc
286
+ if options.fetch(:children, true)
287
+ children.values.each {|child| child.to_xml(options, doc.xpath("//term[@name=\"#{name}\"]/children").first)}
288
+ end
289
+ return doc
270
- xml.default_content_path default_content_path
271
- end
272
- xml.xpath {
273
- xml.relative xpath_relative
274
- xml.absolute xpath
275
- xml.constrained xpath_constrained
276
- }
277
- if options.fetch(:children, true)
278
- xml.children
279
- end
280
- }
281
- end
282
- doc = builder.doc
283
- if options.fetch(:children, true)
284
- children.values.each {|child| child.to_xml(options, doc.xpath("//term[@name=\"#{name}\"]/children").first)}
285
290
end
286
- return doc
287
- end
288
-
289
- # private :update_xpath_values
290
291
292
+ # private :update_xpath_values
293
+ end
291
294
end
data/lib/om/xml/term_builder.rb CHANGED
@@ -93,7 +93,7 @@ module OM::XML::TermBuilder
93
93
# @param [OM::XML::Terminology] terminology that this Term is being built for
94
94
def build(terminology=nil)
95
95
self.resolve_refs!
96
- if term.self.settings.has_key?(:proxy)
96
+ if settings.has_key?(:proxy)
97
97
term = OM::XML::NamedTermProxy.new(self.name, self.settings[:proxy], terminology, self.settings)
98
98
else
99
99
term = OM::XML::Term.new(self.name, {}, terminology)
@@ -118,14 +118,45 @@ module OM::XML::TermBuilder
118
118
return self
119
119
end
120
120
121
+ def root_term= val
122
+ @settings[:is_root_term] = val
123
+ end
121
124
122
- # Any unknown method calls will add an entry to the settings hash and return the current object
123
- def method_missing method, *args, &block
124
- if args.length == 1
125
- args = args.first
126
- end
127
- @settings[method] = args
128
- return self
125
+ def index_as= val
126
+ @settings[:index_as] = val
127
+ end
128
+
129
+ def required= val
130
+ @settings[:required] = val
131
+ end
132
+
133
+ def ref= val
134
+ @settings[:ref] = val
135
+ end
136
+
137
+ def attributes= val
138
+ @settings[:attributes] = val
139
+ end
140
+
141
+ def proxy= val
142
+ @settings[:proxy] = val
143
+ end
144
+
145
+ def type= val
146
+ @settings[:type] = val
147
+ end
148
+
149
+ def path= val
150
+ @settings[:path] = val
129
151
end
152
+
153
+ def variant_of= val
154
+ @settings[:variant_of] = val
155
+ end
156
+
157
+ def default_content_path= val
158
+ @settings[:default_content_path] = val
159
+ end
160
+
130
161
end
131
162
end
data/lib/om/xml/terminology.rb CHANGED
@@ -51,7 +51,10 @@ class OM::XML::Terminology
51
51
@namespaces["oxns"] = ns_pair.last
52
52
end
53
53
end
54
- root_term_builder = OM::XML::Term::Builder.new(opts.fetch(:path,:root).to_s.sub(/[_!]#x2F;, '')).is_root_term(true)
54
+ path = opts.fetch(:path,:root).to_s.sub(/[_!]#x2F;, '')
55
+ root_term_builder = OM::XML::Term::Builder.new(path).tap do |t|
56
+ t.root_term= true
57
+ end
55
58
term_opts = opts.dup
56
59
term_opts.delete(:schema)
57
60
root_term_builder.settings.merge!(term_opts)
data/lib/om/xml/terminology_based_solrizer.rb CHANGED
@@ -15,7 +15,7 @@ module OM::XML::TerminologyBasedSolrizer
15
15
def solrize(doc, solr_doc=Hash.new, field_mapper = nil)
16
16
unless doc.class.terminology.nil?
17
17
doc.class.terminology.terms.each_pair do |term_name,term|
18
- doc.solrize_term(term, solr_doc, field_mapper)
18
+ doc.solrize_term(term, solr_doc, field_mapper) unless term.is_root_term?
19
19
end
20
20
end
21
21
data/om.gemspec CHANGED
@@ -32,8 +32,7 @@ Gem::Specification.new do |s|
32
32
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
33
33
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
34
34
s.extra_rdoc_files = [
35
- "LICENSE",
35
+ "LICENSE"
36
- "README.textile"
37
36
]
38
37
s.require_paths = ["lib"]
39
38
end
data/spec/integration/serialization_spec.rb CHANGED
@@ -1,4 +1,5 @@
1
1
require 'spec_helper'
2
+ require 'active_support/core_ext/string/conversions' # for String#to_time conversion
2
3
3
4
describe "element values" do
4
5
before(:all) do
@@ -20,7 +21,7 @@ describe "element values" do
20
21
21
22
22
23
describe "when the xml template has existing values" do
23
- subject do
24
+ let(:datastream) do
24
25
ElementValueTerminology.from_xml <<-EOF
25
26
<outer outerId="hypatia:outer" type="outer type">
26
27
<my_date>2012-10-30</my_date>
@@ -30,6 +31,7 @@ describe "element values" do
30
31
</outer>
31
32
EOF
32
33
end
34
+ subject { datastream }
33
35
describe "reading values" do
34
36
it "should deserialize date" do
35
37
subject.my_date.should == [Date.parse('2012-10-30')]
@@ -45,26 +47,42 @@ EOF
45
47
end
46
48
end
47
49
describe "Writing to xml" do
48
- it "should serialize time" do
49
- subject.my_time = [DateTime.parse('2011-01-30T03:45:15Z')]
50
- subject.to_xml.should be_equivalent_to '<?xml version="1.0"?>
51
- <outer outerId="hypatia:outer" type="outer type">
52
- <my_date>2012-10-30</my_date>
53
- <my_time>2011-01-30T03:45:15Z</my_time>
54
- <my_int>7</my_int>
55
- <active>true</active>
56
- </outer>'
50
+ context "serializing time" do
51
+ context "with a valid time" do
52
+ subject { datastream.to_xml }
53
+ before { datastream.my_time = [DateTime.parse('2011-01-30T03:45:15Z')] }
54
+ it { should be_equivalent_to '<?xml version="1.0"?>
55
+ <outer outerId="hypatia:outer" type="outer type">
56
+ <my_date>2012-10-30</my_date>
57
+ <my_time>2011-01-30T03:45:15Z</my_time>
58
+ <my_int>7</my_int>
59
+ <active>true</active>
60
+ </outer>' }
61
+ end
62
+
63
+ context "setting an invalid time" do
64
+ it "raises a type mismatch error" do
65
+ expect { datastream.my_time = '' }.to raise_error OM::TypeMismatch
66
+ end
67
+ end
57
68
end
58
- it "should serialize date" do
59
- subject.my_date = [Date.parse('2012-09-22')]
60
- subject.to_xml.should be_equivalent_to '<?xml version="1.0"?>
61
- <outer outerId="hypatia:outer" type="outer type">
62
- <my_date>2012-09-22</my_date>
63
- <my_time>2012-10-30T12:22:33Z</my_time>
64
- <my_int>7</my_int>
65
- <active>true</active>
66
- </outer>'
69
+
70
+ context "serializing dates" do
71
+
72
+ subject { datastream.to_xml }
73
+ context "with a valid date" do
74
+
75
+ before { datastream.my_date = [Date.parse('2012-09-22')] }
76
+ it { should be_equivalent_to '<?xml version="1.0"?>
77
+ <outer outerId="hypatia:outer" type="outer type">
78
+ <my_date>2012-09-22</my_date>
79
+ <my_time>2012-10-30T12:22:33Z</my_time>
80
+ <my_int>7</my_int>
81
+ <active>true</active>
82
+ </outer>' }
83
+ end
67
84
end
85
+
68
86
it "should serialize ints" do
69
87
subject.my_int = [9]
70
88
subject.to_xml.should be_equivalent_to '<?xml version="1.0"?>
data/spec/integration/subclass_terminology_spec.rb CHANGED
@@ -12,6 +12,9 @@ describe "Inherited terminology" do
12
12
end
13
13
14
14
class ConcreteTerminology < AbstractTerminology
15
+ extend_terminology do |t|
16
+ t.bar
17
+ end
15
18
end
16
19
end
17
20
@@ -20,7 +23,7 @@ describe "Inherited terminology" do
20
23
Object.send(:remove_const, :AbstractTerminology)
21
24
end
22
25
23
- describe "on the subclass" do
26
+ describe "the subclass" do
24
27
subject do
25
28
xml = '<root xmlns="asdf"><foo>fooval</foo><bar>barval</bar></root>'
26
29
ConcreteTerminology.from_xml(xml)
@@ -30,9 +33,14 @@ describe "Inherited terminology" do
30
33
subject.foo = "Test value"
31
34
subject.foo.should == ["Test value"]
32
35
end
36
+
37
+ it "should have extended terminology" do
38
+ subject.bar = "Test value"
39
+ subject.bar.should == ["Test value"]
40
+ end
33
41
end
34
42
35
- describe "on the superclass" do
43
+ describe "the superclass" do
36
44
subject do
37
45
xml = '<root xmlns="asdf"><foo>fooval</foo><bar>barval</bar></root>'
38
46
AbstractTerminology.from_xml(xml)
@@ -42,6 +50,10 @@ describe "Inherited terminology" do
42
50
subject.foo = "Test value"
43
51
subject.foo.should == ["Test value"]
44
52
end
53
+
54
+ it "should not have extended terminology" do
55
+ expect { subject.bar }.to raise_error NoMethodError
56
+ end
45
57
end
46
58
end
47
59
data/spec/unit/container_spec.rb CHANGED
@@ -54,7 +54,7 @@ describe "OM::XML::Container" do
54
54
55
55
it 'should accept an optional Nokogiri::XML Document as an argument and insert its fields into that (mocked test)' do
56
56
doc = Nokogiri::XML::Document.parse("<test_xml/>")
57
- mock_new_node = mock("new node")
57
+ mock_new_node = double("new node")
58
58
doc.root.should_receive(:add_child).with(subject.ng_xml.root).and_return(mock_new_node)
59
59
result = subject.to_xml(doc)
60
60
end
@@ -65,7 +65,7 @@ describe "OM::XML::Container" do
65
65
end
66
66
67
67
it 'should add to root of Nokogiri::XML::Documents, but add directly to the elements if a Nokogiri::XML::Node is passed in' do
68
- mock_new_node = mock("new node")
68
+ mock_new_node = double("new node")
69
69
mock_new_node.stub(:to_xml).and_return("foo")
70
70
71
71
doc = Nokogiri::XML::Document.parse("<test_document/>")
data/spec/unit/dynamic_node_spec.rb CHANGED
@@ -47,6 +47,11 @@ describe "OM::XML::DynamicNode" do
47
47
@sample.date_created = ['A long time ago']
48
48
@sample.date_created.should == ['A long time ago']
49
49
end
50
+
51
+ it "checks inequality" do
52
+ @sample.foo = ['in a galaxy far far away']
53
+ expect(@sample.foo != ['nearby']).to be true
54
+ end
50
55
end
51
56
52
57
@@ -80,6 +85,10 @@ describe "OM::XML::DynamicNode" do
80
85
@article.person.last_name.first.should == "FAMILY NAME"
81
86
end
82
87
88
+ it "should respond_to? things an array can do" do
89
+ expect(@article.person.last_name).to respond_to(:map)
90
+ end
91
+
83
92
it "should delegate with blocks to the found array" do
84
93
arr = []
85
94
@article.person.last_name.each{|x| arr << x}
@@ -161,6 +170,20 @@ describe "OM::XML::DynamicNode" do
161
170
@article.journal.title_info = %W(six seven)
162
171
@article.journal.title_info.should == ["six", "seven"]
163
172
end
173
+
174
+ describe '==' do
175
+ it "returns true when values of dynamic nodes are equal." do
176
+ @article.name(0).last_name = "Steven"
177
+ @article.name(0).first_name = "Steven"
178
+ (@article.name(0).last_name == @article.name(0).first_name).should == true
179
+ end
180
+
181
+ it 'returns false when values of dynamic nodes are not equal.' do
182
+ @article.name(0).first_name = "Horatio"
183
+ @article.name(0).last_name = "Hogginobble"
184
+ (@article.name(0).last_name == @article.name(0).first_name).should == false
185
+ end
186
+ end
164
187
end
165
188
end
166
189
end
data/spec/unit/term_builder_spec.rb CHANGED
@@ -33,7 +33,7 @@ describe "OM::XML::Term::Builder" do
33
33
34
34
describe '#new' do
35
35
it "should set terminology_builder attribute if provided" do
36
- mock_terminology_builder = mock("TerminologyBuilder")
36
+ mock_terminology_builder = double("TerminologyBuilder")
37
37
OM::XML::Term::Builder.new("term1", mock_terminology_builder).terminology_builder.should == mock_terminology_builder
38
38
end
39
39
end
@@ -41,17 +41,19 @@ describe "OM::XML::Term::Builder" do
41
41
describe "configuration methods" do
42
42
it "should set the corresponding .settings value return the mapping object" do
43
43
[:path, :index_as, :required, :type, :variant_of, :path, :attributes, :default_content_path].each do |method_name|
44
- @test_builder.send(method_name, "#{method_name.to_s}foo").should == @test_builder
44
+ @test_builder.send("#{method_name}=".to_sym, "#{method_name.to_s}foo")
45
45
@test_builder.settings[method_name].should == "#{method_name.to_s}foo"
46
46
end
47
47
end
48
- it "should be chainable" do
49
- test_builder = OM::XML::Term::Builder.new("chainableTerm").index_as(:facetable, :searchable, :sortable, :displayable).required(true).type(:text)
50
- resulting_settings = test_builder.settings
51
- resulting_settings[:index_as].should == [:facetable, :searchable, :sortable, :displayable]
52
- resulting_settings[:required].should == true
53
- resulting_settings[:type].should == :text
54
- end
48
+ # it "should be chainable" do
49
+ # test_builder = OM::XML::Term::Builder.new("chainableTerm").tap do |t|
50
+ # t.index_as = [:facetable, :searchable, :sortable, :displayable).required(true).type(:text)
51
+ # end
52
+ # resulting_settings = test_builder.settings
53
+ # resulting_settings[:index_as].should == [:facetable, :searchable, :sortable, :displayable]
54
+ # resulting_settings[:required].should == true
55
+ # resulting_settings[:type].should == :text
56
+ # end
55
57
end
56
58
57
59
describe "settings" do
@@ -70,7 +72,6 @@ describe "OM::XML::Term::Builder" do
70
72
it "should insert the given Term Builder into the current Term Builder's children" do
71
73
@test_builder.add_child(@test_builder_2)
72
74
@test_builder.children[@test_builder_2.name].should == @test_builder_2
73
- @test_builder.ancestors.should include(@test_builder_2)
74
75
end
75
76
end
76
77
describe ".retrieve_child" do
@@ -88,7 +89,11 @@ describe "OM::XML::Term::Builder" do
88
89
89
90
describe ".build" do
90
91
it "should build a Term with the given settings and generate its xpath values" do
91
- test_builder = OM::XML::Term::Builder.new("requiredTextFacet").index_as([:facetable, :searchable, :sortable, :displayable]).required(true).type(:text)
92
+ test_builder = OM::XML::Term::Builder.new("requiredTextFacet").tap do |t|
93
+ t.index_as = [:facetable, :searchable, :sortable, :displayable]
94
+ t.required = true
95
+ t.type = :text
96
+ end
92
97
result = test_builder.build
93
98
result.should be_instance_of OM::XML::Term
94
99
result.index_as.should == [:facetable, :searchable, :sortable, :displayable]
@@ -100,7 +105,9 @@ describe "OM::XML::Term::Builder" do
100
105
result.xpath_relative.should == OM::XML::TermXpathGenerator.generate_relative_xpath(result)
101
106
end
102
107
it "should create proxy terms if :proxy is set" do
103
- test_builder = OM::XML::Term::Builder.new("my_proxy").proxy([:foo, :bar])
108
+ test_builder = OM::XML::Term::Builder.new("my_proxy").tap do |t|
109
+ t.proxy = [:foo, :bar]
110
+ end
104
111
result = test_builder.build
105
112
result.should be_kind_of OM::XML::NamedTermProxy
106
113
end
@@ -113,8 +120,8 @@ describe "OM::XML::Term::Builder" do
113
120
built_child1 = OM::XML::Term.new("child1")
114
121
built_child2 = OM::XML::Term.new("child2")
115
122
116
- mock1 = mock("Builder1", :build => built_child1 )
117
- mock2 = mock("Builder2", :build => built_child2 )
123
+ mock1 = double("Builder1", :build => built_child1 )
124
+ mock2 = double("Builder2", :build => built_child2 )
118
125
mock1.stub(:name).and_return("child1")
119
126
mock2.stub(:name).and_return("child2")
120
127
@@ -137,10 +144,17 @@ describe "OM::XML::Term::Builder" do
137
144
@almond.lookup_refs.should == [@peach, @stone_fruit]
138
145
end
139
146
it "should raise an error if the TermBuilder does not have a reference to a terminology builder" do
140
- lambda { OM::XML::Term::Builder.new("referrer").ref("bongos").lookup_refs }.should raise_error(StandardError,"Cannot perform lookup_ref for the referrer builder. It doesn't have a reference to any terminology builder")
147
+ lambda {
148
+ OM::XML::Term::Builder.new("referrer").tap do |t|
149
+ t.ref="bongos"
150
+ t.lookup_refs
151
+ end
152
+ }.should raise_error(StandardError,"Cannot perform lookup_ref for the referrer builder. It doesn't have a reference to any terminology builder")
141
153
end
142
154
it "should raise an error if the referece points to a nonexistent term builder" do
143
- tb = OM::XML::Term::Builder.new("mork",@test_terminology_builder).ref(:characters, :aliens)
155
+ tb = OM::XML::Term::Builder.new("mork",@test_terminology_builder).tap do |t|
156
+ t.ref = [:characters, :aliens]
157
+ end
144
158
lambda { tb.lookup_refs }.should raise_error(OM::XML::Terminology::BadPointerError,"This TerminologyBuilder does not have a root TermBuilder defined that corresponds to \":characters\"")
145
159
end
146
160
it "should raise an error with informative error when given circular references" do
@@ -158,7 +172,9 @@ describe "OM::XML::Term::Builder" do
158
172
@test_builder.children.should == children_pre
159
173
end
160
174
it "should should look up the referenced TermBuilder, use its settings and duplicate its children without changing the name" do
161
- term_builder = OM::XML::Term::Builder.new("orange",@test_terminology_builder).ref(:fruit_trees, :citrus)
175
+ term_builder = OM::XML::Term::Builder.new("orange",@test_terminology_builder).tap do |b|
176
+ b.ref = [:fruit_trees, :citrus]
177
+ end
162
178
term_builder.resolve_refs!
163
179
# Make sure children and settings were copied
164
180
term_builder.settings.should == @citrus.settings.merge(:path=>"citrus")
@@ -174,7 +190,9 @@ describe "OM::XML::Term::Builder" do
174
190
@almond.settings[:path].should == "prunus"
175
191
end
176
192
it "should set path based on the first ref's name if no path is set" do
177
- orange_builder = OM::XML::Term::Builder.new("orange",@test_terminology_builder).ref(:fruit_trees, :citrus)
193
+ orange_builder = OM::XML::Term::Builder.new("orange",@test_terminology_builder).tap do |b|
194
+ b.ref= [:fruit_trees, :citrus]
195
+ end
178
196
orange_builder.resolve_refs!
179
197
orange_builder.settings[:path].should == "citrus"
180
198
end
@@ -182,7 +200,11 @@ describe "OM::XML::Term::Builder" do
182
200
it "should result in clean trees of Terms after building"
183
201
184
202
it "should preserve any extra settings specific to this builder (for variant terms)" do
185
- tb = OM::XML::Term::Builder.new("orange",@test_terminology_builder).ref(:fruit_trees, :citrus).attributes(:color=>"orange").required(true)
203
+ tb = OM::XML::Term::Builder.new("orange",@test_terminology_builder).tap do |b|
204
+ b.ref= [:fruit_trees, :citrus]
205
+ b.attributes = {color: "orange"}
206
+ b.required =true
207
+ end
186
208
tb.resolve_refs!
187
209
tb.settings.should == {:path=>"citrus", :attributes=>{"citric_acid"=>"true", :color=>"orange"}, :required=>true, :type=>:string, :index_as=>[:facetable]}
188
210
end
data/spec/unit/term_spec.rb CHANGED
@@ -75,8 +75,8 @@ describe OM::XML::Term do
75
75
76
76
describe ".retrieve_term" do
77
77
it "should crawl down into mapper children to find the desired term" do
78
- mock_role = mock("mapper", :children =>{:text=>"the target"})
79
- mock_conference = mock("mapper", :children =>{:role=>mock_role})
78
+ mock_role = double("mapper", :children =>{:text=>"the target"})
79
+ mock_conference = double("mapper", :children =>{:role=>mock_role})
80
80
@test_name_part.should_receive(:children).and_return({:conference=>mock_conference})
81
81
@test_name_part.retrieve_term(:conference, :role, :text).should == "the target"
82
82
end
@@ -185,7 +185,7 @@ describe OM::XML::Term do
185
185
@test_volume.xpath_constrained.should == '//detail[@type="volume" and contains(number, "#{constraint_value}")]'.gsub('"', '\"')
186
186
end
187
187
it "should trigger update on any child objects" do
188
- mock_child = mock("child term")
188
+ mock_child = double("child term")
189
189
mock_child.should_receive(:generate_xpath_queries!).exactly(3).times
190
190
@test_name_part.should_receive(:children).and_return({1=>mock_child, 2=>mock_child, 3=>mock_child})
191
191
@test_name_part.generate_xpath_queries!
data/spec/unit/term_xpath_generator_spec.rb CHANGED
@@ -68,7 +68,7 @@ describe "OM::XML::TermXpathGeneratorSpec" do
68
68
OM::XML::TermXpathGenerator.generate_absolute_xpath(@test_term).should == '//namePart[@type="termsOfAddress"]'
69
69
end
70
70
it "should prepend the xpath for any parent nodes" do
71
- mock_parent_mapper = mock("Term", :xpath_absolute=>'//name[@type="conference"]/role')
71
+ mock_parent_mapper = double("Term", :xpath_absolute=>'//name[@type="conference"]/role')
72
72
@test_role_text.stub(:parent => mock_parent_mapper)
73
73
OM::XML::TermXpathGenerator.generate_absolute_xpath(@test_role_text).should == '//name[@type="conference"]/role/roleTerm[@type="text"]'
74
74
end
data/spec/unit/xml_terminology_based_solrizer_spec.rb CHANGED
@@ -29,6 +29,7 @@ describe OM::XML::TerminologyBasedSolrizer do
29
29
solr_doc = Hash.new
30
30
@mods_article.field_mapper = Solrizer::FieldMapper.new
31
31
Samples::ModsArticle.terminology.terms.each_pair do |k,v|
32
+ next if k == :mods # we don't index the root node
32
33
@mods_article.should_receive(:solrize_term).with(v, solr_doc, @mods_article.field_mapper)
33
34
end
34
35
@mods_article.to_solr(solr_doc)
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
--- !ruby/object:Gem::Specification
2
2
name: om
3
3
version: !ruby/object:Gem::Version
4
- version: 3.0.3
4
+ version: 3.0.5
5
- prerelease:
6
5
platform: ruby
7
6
authors:
8
7
- Matt Zumwalt
@@ -10,217 +9,191 @@ authors:
10
9
autorequire:
11
10
bindir: bin
12
11
cert_chain: []
13
- date: 2013-07-19 00:00:00.000000000 Z
12
+ date: 2014-06-05 00:00:00.000000000 Z
14
13
dependencies:
15
14
- !ruby/object:Gem::Dependency
16
15
name: activesupport
17
16
requirement: !ruby/object:Gem::Requirement
18
- none: false
19
17
requirements:
20
- - - ! '>='
18
+ - - ">="
21
19
- !ruby/object:Gem::Version
22
20
version: '0'
23
21
type: :runtime
24
22
prerelease: false
25
23
version_requirements: !ruby/object:Gem::Requirement
26
- none: false
27
24
requirements:
28
- - - ! '>='
25
+ - - ">="
29
26
- !ruby/object:Gem::Version
30
27
version: '0'
31
28
- !ruby/object:Gem::Dependency
32
29
name: activemodel
33
30
requirement: !ruby/object:Gem::Requirement
34
- none: false
35
31
requirements:
36
- - - ! '>='
32
+ - - ">="
37
33
- !ruby/object:Gem::Version
38
34
version: '0'
39
35
type: :runtime
40
36
prerelease: false
41
37
version_requirements: !ruby/object:Gem::Requirement
42
- none: false
43
38
requirements:
44
- - - ! '>='
39
+ - - ">="
45
40
- !ruby/object:Gem::Version
46
41
version: '0'
47
42
- !ruby/object:Gem::Dependency
48
43
name: solrizer
49
44
requirement: !ruby/object:Gem::Requirement
50
- none: false
51
45
requirements:
52
- - - ~>
46
+ - - "~>"
53
47
- !ruby/object:Gem::Version
54
48
version: 3.1.0
55
49
type: :runtime
56
50
prerelease: false
57
51
version_requirements: !ruby/object:Gem::Requirement
58
- none: false
59
52
requirements:
60
- - - ~>
53
+ - - "~>"
61
54
- !ruby/object:Gem::Version
62
55
version: 3.1.0
63
56
- !ruby/object:Gem::Dependency
64
57
name: nokogiri
65
58
requirement: !ruby/object:Gem::Requirement
66
- none: false
67
59
requirements:
68
- - - ! '>='
60
+ - - ">="
69
61
- !ruby/object:Gem::Version
70
62
version: 1.4.2
71
63
type: :runtime
72
64
prerelease: false
73
65
version_requirements: !ruby/object:Gem::Requirement
74
- none: false
75
66
requirements:
76
- - - ! '>='
67
+ - - ">="
77
68
- !ruby/object:Gem::Version
78
69
version: 1.4.2
79
70
- !ruby/object:Gem::Dependency
80
71
name: mediashelf-loggable
81
72
requirement: !ruby/object:Gem::Requirement
82
- none: false
83
73
requirements:
84
- - - ! '>='
74
+ - - ">="
85
75
- !ruby/object:Gem::Version
86
76
version: '0'
87
77
type: :runtime
88
78
prerelease: false
89
79
version_requirements: !ruby/object:Gem::Requirement
90
- none: false
91
80
requirements:
92
- - - ! '>='
81
+ - - ">="
93
82
- !ruby/object:Gem::Version
94
83
version: '0'
95
84
- !ruby/object:Gem::Dependency
96
85
name: deprecation
97
86
requirement: !ruby/object:Gem::Requirement
98
- none: false
99
87
requirements:
100
- - - ! '>='
88
+ - - ">="
101
89
- !ruby/object:Gem::Version
102
90
version: '0'
103
91
type: :runtime
104
92
prerelease: false
105
93
version_requirements: !ruby/object:Gem::Requirement
106
- none: false
107
94
requirements:
108
- - - ! '>='
95
+ - - ">="
109
96
- !ruby/object:Gem::Version
110
97
version: '0'
111
98
- !ruby/object:Gem::Dependency
112
99
name: rspec
113
100
requirement: !ruby/object:Gem::Requirement
114
- none: false
115
101
requirements:
116
- - - ~>
102
+ - - "~>"
117
103
- !ruby/object:Gem::Version
118
104
version: '2.0'
119
105
type: :development
120
106
prerelease: false
121
107
version_requirements: !ruby/object:Gem::Requirement
122
- none: false
123
108
requirements:
124
- - - ~>
109
+ - - "~>"
125
110
- !ruby/object:Gem::Version
126
111
version: '2.0'
127
112
- !ruby/object:Gem::Dependency
128
113
name: rake
129
114
requirement: !ruby/object:Gem::Requirement
130
- none: false
131
115
requirements:
132
- - - ! '>='
116
+ - - ">="
133
117
- !ruby/object:Gem::Version
134
118
version: '0'
135
119
type: :development
136
120
prerelease: false
137
121
version_requirements: !ruby/object:Gem::Requirement
138
- none: false
139
122
requirements:
140
- - - ! '>='
123
+ - - ">="
141
124
- !ruby/object:Gem::Version
142
125
version: '0'
143
126
- !ruby/object:Gem::Dependency
144
127
name: yard
145
128
requirement: !ruby/object:Gem::Requirement
146
- none: false
147
129
requirements:
148
- - - ! '>='
130
+ - - ">="
149
131
- !ruby/object:Gem::Version
150
132
version: '0'
151
133
type: :development
152
134
prerelease: false
153
135
version_requirements: !ruby/object:Gem::Requirement
154
- none: false
155
136
requirements:
156
- - - ! '>='
137
+ - - ">="
157
138
- !ruby/object:Gem::Version
158
139
version: '0'
159
140
- !ruby/object:Gem::Dependency
160
141
name: rdoc
161
142
requirement: !ruby/object:Gem::Requirement
162
- none: false
163
143
requirements:
164
- - - ! '>='
144
+ - - ">="
165
145
- !ruby/object:Gem::Version
166
146
version: '0'
167
147
type: :development
168
148
prerelease: false
169
149
version_requirements: !ruby/object:Gem::Requirement
170
- none: false
171
150
requirements:
172
- - - ! '>='
151
+ - - ">="
173
152
- !ruby/object:Gem::Version
174
153
version: '0'
175
154
- !ruby/object:Gem::Dependency
176
155
name: RedCloth
177
156
requirement: !ruby/object:Gem::Requirement
178
- none: false
179
157
requirements:
180
- - - ! '>='
158
+ - - ">="
181
159
- !ruby/object:Gem::Version
182
160
version: '0'
183
161
type: :development
184
162
prerelease: false
185
163
version_requirements: !ruby/object:Gem::Requirement
186
- none: false
187
164
requirements:
188
- - - ! '>='
165
+ - - ">="
189
166
- !ruby/object:Gem::Version
190
167
version: '0'
191
168
- !ruby/object:Gem::Dependency
192
169
name: awesome_print
193
170
requirement: !ruby/object:Gem::Requirement
194
- none: false
195
171
requirements:
196
- - - ! '>='
172
+ - - ">="
197
173
- !ruby/object:Gem::Version
198
174
version: '0'
199
175
type: :development
200
176
prerelease: false
201
177
version_requirements: !ruby/object:Gem::Requirement
202
- none: false
203
178
requirements:
204
- - - ! '>='
179
+ - - ">="
205
180
- !ruby/object:Gem::Version
206
181
version: '0'
207
182
- !ruby/object:Gem::Dependency
208
183
name: equivalent-xml
209
184
requirement: !ruby/object:Gem::Requirement
210
- none: false
211
185
requirements:
212
- - - ! '>='
186
+ - - ">="
213
187
- !ruby/object:Gem::Version
214
188
version: 0.2.4
215
189
type: :development
216
190
prerelease: false
217
191
version_requirements: !ruby/object:Gem::Requirement
218
- none: false
219
192
requirements:
220
- - - ! '>='
193
+ - - ">="
221
194
- !ruby/object:Gem::Version
222
195
version: 0.2.4
223
- description: ! 'OM (Opinionated Metadata): A library to help you tame sprawling XML
196
+ description: 'OM (Opinionated Metadata): A library to help you tame sprawling XML
224
197
schemas like MODS. Wraps Nokogiri documents in objects with miscellaneous helper
225
198
methods for doing things like retrieve generated xpath queries or look up properties
226
199
based on a simplified DSL'
@@ -229,19 +202,19 @@ executables: []
229
202
extensions: []
230
203
extra_rdoc_files:
231
204
- LICENSE
232
- - README.textile
233
205
files:
234
- - .document
235
- - .gitignore
236
- - .travis.yml
206
+ - ".document"
207
+ - ".gitignore"
208
+ - ".travis.yml"
237
209
- COMMON_OM_PATTERNS.textile
210
+ - CONTRIBUTING.md
238
211
- GETTING_FANCY.textile
239
212
- GETTING_STARTED.textile
240
213
- Gemfile
241
214
- History.textile
242
215
- LICENSE
243
216
- QUERYING_DOCUMENTS.textile
244
- - README.textile
217
+ - README.md
245
218
- Rakefile
246
219
- UPDATING_DOCUMENTS.textile
247
220
- container_spec.rb
@@ -309,28 +282,27 @@ files:
309
282
- spec/unit/xml_terminology_based_solrizer_spec.rb
310
283
homepage: http://github.com/projecthydra/om
311
284
licenses: []
285
+ metadata: {}
312
286
post_install_message:
313
287
rdoc_options: []
314
288
require_paths:
315
289
- lib
316
290
required_ruby_version: !ruby/object:Gem::Requirement
317
- none: false
318
291
requirements:
319
- - - ! '>='
292
+ - - ">="
320
293
- !ruby/object:Gem::Version
321
294
version: 1.9.3
322
295
required_rubygems_version: !ruby/object:Gem::Requirement
323
- none: false
324
296
requirements:
325
- - - ! '>='
297
+ - - ">="
326
298
- !ruby/object:Gem::Version
327
299
version: '0'
328
300
requirements: []
329
301
rubyforge_project:
330
- rubygems_version: 1.8.23
302
+ rubygems_version: 2.2.2
331
303
signing_key:
332
- specification_version: 3
333
- summary: ! 'OM (Opinionated Metadata): A library to help you tame sprawling XML schemas
304
+ specification_version: 4
305
+ summary: 'OM (Opinionated Metadata): A library to help you tame sprawling XML schemas
334
306
like MODS.'
335
307
test_files:
336
308
- spec/fixtures/CBF_MODS/ARS0025_016.xml