om 3.1.0 → 3.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/{COMMON_OM_PATTERNS.textile → COMMON_OM_PATTERNS.md} +136 -126
- data/CONTRIBUTING.md +2 -2
- data/GETTING_FANCY.md +153 -0
- data/GETTING_STARTED.md +329 -0
- data/Gemfile +1 -1
- data/History.md +164 -0
- data/LICENSE +15 -20
- data/QUERYING_DOCUMENTS.md +162 -0
- data/README.md +2 -2
- data/UPDATING_DOCUMENTS.md +6 -0
- data/gemfiles/gemfile.rails3 +1 -1
- data/gemfiles/gemfile.rails4 +1 -1
- data/lib/om/version.rb +1 -1
- data/lib/om/xml/dynamic_node.rb +42 -51
- data/lib/tasks/om.rake +1 -1
- data/om.gemspec +1 -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 +10 -10
- data/spec/integration/querying_documents_spec.rb +20 -27
- data/spec/integration/rights_metadata_integration_example_spec.rb +4 -4
- data/spec/integration/selective_querying_spec.rb +1 -1
- data/spec/integration/serialization_spec.rb +15 -15
- data/spec/integration/set_reentrant_terminology_spec.rb +6 -6
- data/spec/integration/subclass_terminology_spec.rb +8 -8
- data/spec/integration/xpathy_stuff_spec.rb +10 -10
- data/spec/unit/container_spec.rb +27 -27
- data/spec/unit/document_spec.rb +24 -24
- data/spec/unit/dynamic_node_spec.rb +60 -49
- data/spec/unit/named_term_proxy_spec.rb +12 -7
- data/spec/unit/node_generator_spec.rb +4 -4
- data/spec/unit/nokogiri_sanity_spec.rb +17 -18
- data/spec/unit/om_spec.rb +2 -2
- data/spec/unit/template_registry_spec.rb +51 -51
- data/spec/unit/term_builder_spec.rb +45 -44
- data/spec/unit/term_spec.rb +55 -55
- data/spec/unit/term_value_operators_spec.rb +205 -205
- data/spec/unit/term_xpath_generator_spec.rb +33 -36
- data/spec/unit/terminology_builder_spec.rb +50 -47
- data/spec/unit/terminology_spec.rb +92 -92
- data/spec/unit/validation_spec.rb +12 -12
- data/spec/unit/xml_serialization_spec.rb +20 -20
- data/spec/unit/xml_spec.rb +3 -3
- data/spec/unit/xml_terminology_based_solrizer_spec.rb +18 -18
- metadata +11 -38
- data/GETTING_FANCY.textile +0 -145
- data/GETTING_STARTED.textile +0 -254
- data/History.textile +0 -186
- data/QUERYING_DOCUMENTS.textile +0 -139
- data/UPDATING_DOCUMENTS.textile +0 -3
data/LICENSE
CHANGED
@@ -1,20 +1,15 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
-
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
-
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
-
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
-
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
1
|
+
##########################################################################
|
2
|
+
# Copyright (c) 2009 Matt Zumwalt
|
3
|
+
# Additional copyright may be held by others, as reflected in the commit log
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
@@ -0,0 +1,162 @@
|
|
1
|
+
# Querying OM Documents
|
2
|
+
|
3
|
+
This document will help you understand how to access the information
|
4
|
+
associated with an [OM::XML::Document](OM/XML/Document.html) object. We
|
5
|
+
will explain some of the methods provided by the
|
6
|
+
[OM::XML::Document](OM/XML/Document.html) module and its related modules
|
7
|
+
[OM::XML::TermXPathGenerator](OM/XML/TermXPathGenerator.html) &
|
8
|
+
[OM::XML::TermValueOperators](OM/XML/TermValueOperators.html)
|
9
|
+
|
10
|
+
*Note: In your code, don’t worry about including
|
11
|
+
`OM::XML::TermXPathGenerator` and `OM::XML::TermValueOperators` into your
|
12
|
+
classes. `OM::XML::Document` handles that for you.*
|
13
|
+
|
14
|
+
### Load the Sample XML and Sample Terminology
|
15
|
+
|
16
|
+
These examples use the Document class defined in
|
17
|
+
[OM::Samples::ModsArticle](https://github.com/projecthydra/om/blob/master/lib/om/samples/mods_article.rb)
|
18
|
+
|
19
|
+
Download
|
20
|
+
[hydrangea\_article1.xml](https://github.com/projecthydra/om/blob/master/spec/fixtures/mods_articles/hydrangea_article1.xml)
|
21
|
+
(sample xml) into your working directory, then run this in irb:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
require "om/samples"
|
25
|
+
sample_xml = File.new("hydrangea_article1.xml")
|
26
|
+
doc = OM::Samples::ModsArticle.from_xml(sample_xml)
|
27
|
+
```
|
28
|
+
|
29
|
+
## Querying the [OM::XML::Document](OM/XML/Document.html)
|
30
|
+
|
31
|
+
The [OM::XML::Terminology](OM/XML/Terminology.html") declared by
|
32
|
+
[OM::Samples::ModsArticle](https://github.com/projecthydra/om/blob/master/lib/om/samples/mods_article.rb)
|
33
|
+
maps the defined Terminology structure to xpath queries. It will also run the queries for you in most cases.
|
34
|
+
|
35
|
+
#### xpath\_for method of [OM::XML::Terminology](OM/XML/Terminology.html") retrieves xpath expressions for OM terms
|
36
|
+
|
37
|
+
The `xpath_for` method retrieves the xpath used by the
|
38
|
+
[OM::XML::Terminology](OM/XML/Terminology.html")
|
39
|
+
|
40
|
+
Examples of xpaths for `:name` and two variants of `:name` that were created
|
41
|
+
using the `:ref` argument in the Terminology builder:
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
OM::Samples::ModsArticle.terminology.xpath_for(:name)
|
45
|
+
=> "//oxns:name"
|
46
|
+
OM::Samples::ModsArticle.terminology.xpath_for(:person)
|
47
|
+
=> "//oxns:name[@type=\"personal\"]"
|
48
|
+
OM::Samples::ModsArticle.terminology.xpath_for(:organization)
|
49
|
+
=> "//oxns:name[@type=\"corporate\"]"
|
50
|
+
```
|
51
|
+
|
52
|
+
#### Working with Terms
|
53
|
+
|
54
|
+
To retrieve the values of xml nodes, use the `term_values` method:
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
doc.term_values(:person, :first_name)
|
58
|
+
doc.term_values(:person, :last_name)
|
59
|
+
```
|
60
|
+
|
61
|
+
The `term_values` method is defined in the
|
62
|
+
[OM::XML::TermValueOperators](OM/XML/TermValueOperators.html) module,
|
63
|
+
which is included in [OM::XML::Document](OM/XML/Document.html)
|
64
|
+
|
65
|
+
Not that if a term’s xpath mapping points to XML nodes that contain
|
66
|
+
other nodes, the response to term\_values will be `Nokogiri::XML::Node`
|
67
|
+
objects instead of text values:
|
68
|
+
|
69
|
+
doc.term_values(:name)
|
70
|
+
|
71
|
+
More examples of using term\_values and find\_by\_terms (defined in
|
72
|
+
[OM::XML::Document](OM/XML/Document.html)):
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
doc.find_by_terms(:organization).to_xml
|
76
|
+
doc.term_values(:organization, :role)
|
77
|
+
=> ["\n Funder\n "]
|
78
|
+
doc.term_values(:organization, :namePart)
|
79
|
+
=> ["NSF"]
|
80
|
+
```
|
81
|
+
|
82
|
+
To retrieve the values of nested terms, create a sequence of terms, from
|
83
|
+
outermost to innermost:
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
OM::Samples::ModsArticle.terminology.xpath_for(:journal, :issue, :pages, :start)
|
87
|
+
=> "//oxns:relatedItem[@type=\"host\"]/oxns:part/oxns:extent[@unit=\"pages\"]/oxns:start"
|
88
|
+
doc.term_values(:journal, :issue, :pages, :start)
|
89
|
+
=> ["195"]
|
90
|
+
```
|
91
|
+
|
92
|
+
If you get one of the term names wrong in the sequence, OM will tell you
|
93
|
+
which one is causing problems. See what happens when you put :page
|
94
|
+
instead of :pages in your argument to term\_values.
|
95
|
+
|
96
|
+
```ruby
|
97
|
+
doc.term_values(:journal, :issue, :page, :start)
|
98
|
+
# OM::XML::Terminology::BadPointerError: You attempted to retrieve a Term using this pointer: [:journal, :issue, :page] but no Term exists at that location. Everything is fine until ":page", which doesn't exist.
|
99
|
+
```
|
100
|
+
|
101
|
+
### When XML Elements are Reused in a Document
|
102
|
+
|
103
|
+
Another way to put this: the xpath statement for a term can be ambiguous.
|
104
|
+
|
105
|
+
In our MODS document, we have two distinct uses of the title XML element:
|
106
|
+
|
107
|
+
1. title of the published article,
|
108
|
+
2. title of the journal it was published in.
|
109
|
+
|
110
|
+
How can we distinguish between these two uses?
|
111
|
+
|
112
|
+
```ruby
|
113
|
+
doc.term_values(:title_info, :main_title)
|
114
|
+
=> ["ARTICLE TITLE", "VARYING FORM OF TITLE", "TITLE OF HOST JOURNAL"]
|
115
|
+
doc.term_values(:mods, :title_info, :main_title)
|
116
|
+
=> ["ARTICLE TITLE", "VARYING FORM OF TITLE"]
|
117
|
+
OM::Samples::ModsArticle.terminology.xpath_for(:title_info, :main_title)
|
118
|
+
=> "//oxns:titleInfo/oxns:title"
|
119
|
+
```
|
120
|
+
|
121
|
+
The solution: include the root node in your term pointer.
|
122
|
+
|
123
|
+
```ruby
|
124
|
+
OM::Samples::ModsArticle.terminology.xpath_for(:mods, :title_info, :main_title)
|
125
|
+
=> "//oxns:mods/oxns:titleInfo/oxns:title"
|
126
|
+
doc.term_values(:mods, :title_info, :main_title)
|
127
|
+
=> ["ARTICLE TITLE", "VARYING FORM OF TITLE"]
|
128
|
+
```
|
129
|
+
|
130
|
+
We can still access the Journal title by its own pointers:
|
131
|
+
|
132
|
+
```ruby
|
133
|
+
doc.term_values(:journal, :title_info, :main_title)
|
134
|
+
=> ["TITLE OF HOST JOURNAL"]
|
135
|
+
```
|
136
|
+
|
137
|
+
### Making life easier with Proxy Terms
|
138
|
+
|
139
|
+
If you use a nested term often, you may want to avoid typing the whole
|
140
|
+
sequence of term names by defining a *proxy* term.
|
141
|
+
|
142
|
+
As you can see in
|
143
|
+
[OM::Samples::ModsArticle](https://github.com/projecthydra/om/blob/master/lib/om/samples/mods_article.rb),
|
144
|
+
we have defined a few proxy terms for convenience.
|
145
|
+
|
146
|
+
```ruby
|
147
|
+
t.publication_url(:proxy=>[:location,:url])
|
148
|
+
t.peer_reviewed(:proxy=>[:journal,:origin_info,:issuance], :index_as=>[:facetable])
|
149
|
+
t.title(:proxy=>[:mods,:title_info, :main_title])
|
150
|
+
t.journal_title(:proxy=>[:journal, :title_info, :main_title])
|
151
|
+
```
|
152
|
+
|
153
|
+
You can use proxy terms just like any other term when querying the document.
|
154
|
+
```ruby
|
155
|
+
OM::Samples::ModsArticle.terminology.xpath_for(:peer_reviewed)
|
156
|
+
=> "//oxns:relatedItem[@type=\"host\"]/oxns:originInfo/oxns:issuance"
|
157
|
+
OM::Samples::ModsArticle.terminology.xpath_for(:title)
|
158
|
+
=> "//oxns:mods/oxns:titleInfo/oxns:title"
|
159
|
+
OM::Samples::ModsArticle.terminology.xpath_for(:journal_title)
|
160
|
+
=> "//oxns:relatedItem[@type=\"host\"]/oxns:titleInfo/oxns:title"
|
161
|
+
```
|
162
|
+
|
data/README.md
CHANGED
@@ -12,7 +12,7 @@ OM "terms" are ruby symbols you define (in the terminology) that map specific XM
|
|
12
12
|
## Tutorials & Reference
|
13
13
|
|
14
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.
|
15
|
+
* [Common OM Patterns](https://github.com/projecthydra/om/blob/master/COMMON_OM_PATTERNS.md)
|
16
16
|
|
17
17
|
### Solrizing Documents
|
18
18
|
|
@@ -28,7 +28,7 @@ We have a page on the Hydra wiki with a list of OM Terminologies in active use:
|
|
28
28
|
|
29
29
|
### Creator
|
30
30
|
|
31
|
-
Matt Zumwalt ([MediaShelf](http://yourmediashelf.com)
|
31
|
+
Matt Zumwalt ([MediaShelf](http://yourmediashelf.com))
|
32
32
|
|
33
33
|
### Thanks To
|
34
34
|
|
data/gemfiles/gemfile.rails3
CHANGED
data/gemfiles/gemfile.rails4
CHANGED
data/lib/om/version.rb
CHANGED
data/lib/om/xml/dynamic_node.rb
CHANGED
@@ -3,8 +3,8 @@ module OM
|
|
3
3
|
#
|
4
4
|
# Provides a natural syntax for using OM Terminologies to access values from xml Documents
|
5
5
|
#
|
6
|
-
# *Note*: All of these examples assume that @article is an instance of OM::Samples::ModsArticle. Look at that file to see the Terminology.
|
7
|
-
#
|
6
|
+
# *Note*: All of these examples assume that @article is an instance of OM::Samples::ModsArticle. Look at that file to see the Terminology.
|
7
|
+
#
|
8
8
|
# @example Return an array of the value(s) "start page" node(s) from the second issue node within the first journal node
|
9
9
|
# # Using DynamicNode syntax:
|
10
10
|
# @article.journal(0).issue(1).pages.start
|
@@ -38,37 +38,23 @@ module OM
|
|
38
38
|
self.parent = parent
|
39
39
|
end
|
40
40
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
else
|
51
|
-
val.send(name, *args, &block)
|
52
|
-
end
|
53
|
-
end
|
41
|
+
# In practice, method_missing will respond 4 different ways:
|
42
|
+
# (1) ALL assignment operations are accepted/attempted as new nodes,
|
43
|
+
# (2) ANY operation with multiple arguments is accepted/attempted as a new node (w/ index),
|
44
|
+
# (3) With an auto-constructed sub DynamicNode object,
|
45
|
+
# (4) By handing off to val. This is the only route that will return NoMethodError.
|
46
|
+
#
|
47
|
+
# Here we don't have args, so we cannot handle cases 2 and 3. But we can at least do 1 and 4.
|
48
|
+
def respond_to_missing?(name, include_private = false)
|
49
|
+
/=$/.match(name.to_s) || val.respond_to?(name, include_private) || super
|
54
50
|
end
|
55
51
|
|
56
|
-
def
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
child = term.retrieve_term(modified_name)
|
63
|
-
node = OM::XML::DynamicNode.new(modified_name, nil, @document, child, self)
|
64
|
-
node.val=args
|
65
|
-
end
|
66
|
-
|
67
|
-
def new_update_node_with_index(name, args)
|
68
|
-
index = args.shift
|
69
|
-
child = term.retrieve_term(name)
|
70
|
-
node = OM::XML::DynamicNode.new(name, index, @document, child, self)
|
71
|
-
node.val=args
|
52
|
+
def method_missing(name, *args, &block)
|
53
|
+
return new_update_node(name.to_s.chop.to_sym, nil, args) if /=$/.match(name.to_s)
|
54
|
+
return new_update_node(name, args.shift, args) if args.length > 1
|
55
|
+
child = term_child_by_name(term.nil? ? parent.term : term, name)
|
56
|
+
return OM::XML::DynamicNode.new(name, args.first, @document, child, self) if child
|
57
|
+
val.send(name, *args, &block)
|
72
58
|
end
|
73
59
|
|
74
60
|
def val=(args)
|
@@ -96,18 +82,9 @@ module OM
|
|
96
82
|
end
|
97
83
|
end
|
98
84
|
|
99
|
-
|
100
|
-
def term_child_by_name(term, name)
|
101
|
-
if (term.kind_of? NamedTermProxy)
|
102
|
-
@document.class.terminology.retrieve_node(*(term.proxy_pointer.dup << name))
|
103
|
-
else
|
104
|
-
term.retrieve_term(name)
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
85
|
# This resolves the target of this dynamic node into a reified Array
|
109
86
|
# @return [Array]
|
110
|
-
def val
|
87
|
+
def val
|
111
88
|
query = xpath
|
112
89
|
trim_text = !query.index("text()").nil?
|
113
90
|
val = @document.find_by_xpath(query).collect {|node| (trim_text ? node.text.strip : node.text) }
|
@@ -123,7 +100,7 @@ module OM
|
|
123
100
|
def delete
|
124
101
|
nodeset.delete
|
125
102
|
end
|
126
|
-
|
103
|
+
|
127
104
|
def inspect
|
128
105
|
val.inspect
|
129
106
|
end
|
@@ -146,7 +123,7 @@ module OM
|
|
146
123
|
else ### A pointer
|
147
124
|
parent.nil? ? [key] : parent.to_pointer << key
|
148
125
|
end
|
149
|
-
end
|
126
|
+
end
|
150
127
|
|
151
128
|
def xpath
|
152
129
|
if parent.nil?
|
@@ -155,10 +132,8 @@ module OM
|
|
155
132
|
chain = retrieve_addressed_node( )
|
156
133
|
'//' + chain.map { |n| n.xpath}.join('/')
|
157
134
|
end
|
158
|
-
|
159
135
|
end
|
160
136
|
|
161
|
-
|
162
137
|
class AddressedNode
|
163
138
|
attr_accessor :xpath, :key, :pointer
|
164
139
|
def initialize (pointer, xpath, key)
|
@@ -167,15 +142,12 @@ module OM
|
|
167
142
|
self.pointer = pointer
|
168
143
|
end
|
169
144
|
end
|
170
|
-
|
145
|
+
|
171
146
|
##
|
172
147
|
# This is very similar to Terminology#retrieve_term, however it expands proxy paths out into their cannonical paths
|
173
148
|
def retrieve_addressed_node()
|
174
149
|
chain = []
|
175
|
-
|
176
|
-
if parent
|
177
|
-
chain += parent.retrieve_addressed_node()
|
178
|
-
end
|
150
|
+
chain += parent.retrieve_addressed_node() if parent
|
179
151
|
if (self.index)
|
180
152
|
### This is an index
|
181
153
|
node = AddressedNode.new(key, term.xpath_relative, self)
|
@@ -191,12 +163,31 @@ module OM
|
|
191
163
|
p = p.retrieve_term(first)
|
192
164
|
chain << AddressedNode.new(p, p.xpath_relative, self)
|
193
165
|
end
|
194
|
-
else
|
166
|
+
else
|
195
167
|
chain << AddressedNode.new(key, term.xpath_relative, self)
|
196
168
|
end
|
197
169
|
chain
|
198
170
|
end
|
199
171
|
|
172
|
+
private
|
173
|
+
|
174
|
+
# Only to be called by method_missing, hence the NoMethodError.
|
175
|
+
# We know term.sanitize_new_values would fail in .val= if we pass a nil term.
|
176
|
+
def new_update_node(name, index, args)
|
177
|
+
child = term.retrieve_term(name)
|
178
|
+
raise NoMethodError, "undefined method `#{name}' in OM::XML::DynamicNode for #{self}:#{self.class}" if child.nil?
|
179
|
+
node = OM::XML::DynamicNode.new(name, index, @document, child, self)
|
180
|
+
node.val = args
|
181
|
+
end
|
182
|
+
|
183
|
+
# Only to be called by method_missing
|
184
|
+
def term_child_by_name(term, name)
|
185
|
+
if (term.kind_of? NamedTermProxy)
|
186
|
+
@document.class.terminology.retrieve_node(*(term.proxy_pointer.dup << name))
|
187
|
+
else
|
188
|
+
term.retrieve_term(name)
|
189
|
+
end
|
190
|
+
end
|
200
191
|
|
201
192
|
end
|
202
193
|
end
|
data/lib/tasks/om.rake
CHANGED
@@ -33,7 +33,7 @@ namespace :om do
|
|
33
33
|
doc_destination = File.join(project_root, 'doc')
|
34
34
|
|
35
35
|
YARD::Rake::YardocTask.new(:doc) do |yt|
|
36
|
-
readme_filename = 'README.
|
36
|
+
readme_filename = 'README.md'
|
37
37
|
#yt.options = ['--private', '--protected', '--output-dir', doc_destination, '--readme', readme_filename]
|
38
38
|
end
|
39
39
|
rescue LoadError
|
data/om.gemspec
CHANGED
@@ -9,6 +9,7 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.authors = ["Matt Zumwalt", "Justin Coyne"]
|
10
10
|
s.email = %q{matt.zumwalt@yourmediashelf.com justin.coyne@mediashelf.com}
|
11
11
|
s.homepage = %q{http://github.com/projecthydra/om}
|
12
|
+
s.license = 'APACHE2'
|
12
13
|
s.summary = %q{OM (Opinionated Metadata): A library to help you tame sprawling XML schemas like MODS.}
|
13
14
|
s.description = %q{OM (Opinionated Metadata): A library to help you tame sprawling XML schemas like MODS. Wraps Nokogiri documents in objects with miscellaneous helper methods for doing things like retrieve generated xpath queries or look up properties based on a simplified DSL}
|
14
15
|
|
@@ -21,8 +22,6 @@ Gem::Specification.new do |s|
|
|
21
22
|
s.add_development_dependency "rspec", "~> 2.0"
|
22
23
|
s.add_development_dependency "rake"
|
23
24
|
s.add_development_dependency "yard"
|
24
|
-
s.add_development_dependency "rdoc"
|
25
|
-
s.add_development_dependency "RedCloth" # for textile formatting in rdoc
|
26
25
|
s.add_development_dependency "awesome_print"
|
27
26
|
s.add_development_dependency "equivalent-xml", ">= 0.2.4"
|
28
27
|
|
@@ -30,10 +30,10 @@ describe "use the root element as a member of the proxy address" do
|
|
30
30
|
end
|
31
31
|
|
32
32
|
it "should pull out all occurences of the_thing_we_want in the relevant_container" do
|
33
|
-
subject.relevant_container.the_thing_we_want.
|
33
|
+
expect(subject.relevant_container.the_thing_we_want).to eq ["1", "2"]
|
34
34
|
end
|
35
35
|
|
36
36
|
it "should only pull out the_thing_we_want at the root level" do
|
37
|
-
subject.the_thing_we_want.
|
37
|
+
expect(subject.the_thing_we_want).to eq ["2"]
|
38
38
|
end
|
39
39
|
end
|
@@ -53,39 +53,39 @@ EOF
|
|
53
53
|
end
|
54
54
|
|
55
55
|
it "should handle single-element terms correctly" do
|
56
|
-
subject.elementA.
|
56
|
+
expect(subject.elementA).to eq ["valA"]
|
57
57
|
end
|
58
58
|
|
59
59
|
it "should handle term paths" do
|
60
|
-
subject.elC.
|
60
|
+
expect(subject.elC).to eq ["valC"]
|
61
61
|
end
|
62
62
|
|
63
63
|
it "should handle multiple-element, terms with paths correctly" do
|
64
|
-
subject.elB.
|
64
|
+
expect(subject.elB).to eq ["valB1", "valB2"]
|
65
65
|
end
|
66
66
|
|
67
67
|
it "should handle terms that require specific attributes" do
|
68
|
-
subject.elementC.
|
68
|
+
expect(subject.elementC).to eq ["valC"]
|
69
69
|
end
|
70
70
|
|
71
71
|
it "should handle" do
|
72
|
-
subject.here.length.
|
73
|
-
subject.here.first.split(/\W/).
|
72
|
+
expect(subject.here.length).to eq 1
|
73
|
+
expect(subject.here.first.split(/\W/)).to include('123', '456')
|
74
74
|
end
|
75
75
|
|
76
76
|
it "should handle missing terms" do
|
77
|
-
subject.there.
|
77
|
+
expect(subject.there).to be_empty
|
78
78
|
end
|
79
79
|
|
80
80
|
it "should handle element value given the absence of a specific attribute" do
|
81
|
-
subject.elementD.
|
82
|
-
subject.no_attrib.
|
81
|
+
expect(subject.elementD).to eq ["valD1"]
|
82
|
+
expect(subject.no_attrib).to eq ["valB1"]
|
83
83
|
end
|
84
84
|
|
85
85
|
it "should handle OM terms for an attribute value" do
|
86
|
-
subject.elementB.my_attr.
|
87
|
-
subject.alternate.
|
88
|
-
subject.another.
|
89
|
-
subject.animal_attrib.
|
86
|
+
expect(subject.elementB.my_attr).to eq ["vole"]
|
87
|
+
expect(subject.alternate).to eq ["vole"]
|
88
|
+
expect(subject.another).to eq ["vole"]
|
89
|
+
expect(subject.animal_attrib).to include("vole", "seagull")
|
90
90
|
end
|
91
91
|
end
|