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/lib/om/xml/terminology.rb
CHANGED
@@ -47,7 +47,9 @@ class OM::XML::Terminology
|
|
47
47
|
@schema = opts.fetch(:schema,nil)
|
48
48
|
opts.select {|k,v| k.to_s.include?("xmlns")}.each do |ns_pair|
|
49
49
|
@namespaces[ns_pair.first.to_s] = ns_pair.last
|
50
|
-
|
50
|
+
if ns_pair.first.to_s == "xmlns"
|
51
|
+
@namespaces["oxns"] = ns_pair.last
|
52
|
+
end
|
51
53
|
end
|
52
54
|
root_term_builder = OM::XML::Term::Builder.new(opts.fetch(:path,:root).to_s.sub(/[_!]$/, '')).is_root_term(true)
|
53
55
|
term_opts = opts.dup
|
@@ -55,7 +57,7 @@ class OM::XML::Terminology
|
|
55
57
|
root_term_builder.settings.merge!(term_opts)
|
56
58
|
@term_builders[root_term_builder.name] = root_term_builder
|
57
59
|
|
58
|
-
root_term_builder
|
60
|
+
return root_term_builder
|
59
61
|
end
|
60
62
|
|
61
63
|
# Returns an array of Terms that have been marked as "root" terms
|
@@ -97,7 +99,7 @@ class OM::XML::Terminology
|
|
97
99
|
raise OM::XML::Terminology::BadPointerError, "You attempted to retrieve a TermBuilder using this pointer: #{args.inspect} but no TermBuilder exists at that location. Everything is fine until \"#{arg.inspect}\", which doesn't exist."
|
98
100
|
end
|
99
101
|
end
|
100
|
-
current_term
|
102
|
+
return current_term
|
101
103
|
end
|
102
104
|
|
103
105
|
# Add additional terms into this terminology
|
@@ -135,12 +137,12 @@ class OM::XML::Terminology
|
|
135
137
|
|
136
138
|
# Returns true if the current terminology has a term defined at the location indicated by +pointers+ array
|
137
139
|
def has_term?(*pointers)
|
138
|
-
|
140
|
+
begin
|
139
141
|
retrieve_term(*OM.pointers_to_flat_array(pointers, false))
|
140
142
|
return true
|
141
143
|
rescue
|
142
144
|
return false
|
143
|
-
|
145
|
+
end
|
144
146
|
end
|
145
147
|
|
146
148
|
# Returns the Term corresponding to the given _pointer_.
|
@@ -158,7 +160,7 @@ class OM::XML::Terminology
|
|
158
160
|
end
|
159
161
|
end
|
160
162
|
end
|
161
|
-
current_term
|
163
|
+
return current_term
|
162
164
|
end
|
163
165
|
|
164
166
|
def retrieve_node_subsequent(args, context)
|
@@ -238,7 +240,7 @@ class OM::XML::Terminology
|
|
238
240
|
end
|
239
241
|
|
240
242
|
term = retrieve_term(*term_pointers)
|
241
|
-
term.xml_builder_template(extra_opts)
|
243
|
+
return term.xml_builder_template(extra_opts)
|
242
244
|
end
|
243
245
|
|
244
246
|
# Returns an array of Terms that have been marked as "root" terms
|
@@ -272,7 +274,7 @@ class OM::XML::Terminology
|
|
272
274
|
end
|
273
275
|
document = builder.doc
|
274
276
|
terms.values.each {|term| term.to_xml(options,document.xpath("//terms").first)}
|
275
|
-
document
|
277
|
+
return document
|
276
278
|
end
|
277
279
|
|
278
280
|
def self.term_generic_name(*pointers)
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'solrizer'
|
2
|
+
# This module is only suitable to mix into Classes that use the OM::XML::Document Module
|
3
|
+
module OM::XML::TerminologyBasedSolrizer
|
4
|
+
def self.included(klass)
|
5
|
+
klass.send(:include, ::Solrizer::Common)
|
6
|
+
klass.send(:extend, ClassMethods)
|
7
|
+
end
|
8
|
+
|
9
|
+
# Module Methods
|
10
|
+
module ClassMethods
|
11
|
+
|
12
|
+
# Build a solr document from +doc+ based on its terminology
|
13
|
+
# @param [OM::XML::Document] doc
|
14
|
+
# @param [Hash] (optional) solr_doc (values hash) to populate
|
15
|
+
def solrize(doc, solr_doc=Hash.new, field_mapper = nil)
|
16
|
+
unless doc.class.terminology.nil?
|
17
|
+
doc.class.terminology.terms.each_pair do |term_name,term|
|
18
|
+
doc.solrize_term(term, solr_doc, field_mapper)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
return solr_doc
|
23
|
+
end
|
24
|
+
|
25
|
+
# Populate a solr document with fields based on nodes in +xml+
|
26
|
+
# Values for a term are gathered by to +term_pointer+ using OM::XML::TermValueOperators.term_values
|
27
|
+
# and are deserialized by OM according to :type, as determined in its terminology.
|
28
|
+
# The content of the actual field in solr is each +node+ of the +nodeset+ returned by OM,
|
29
|
+
# rendered to a string.
|
30
|
+
# @param [OM::XML::Document] doc xml document to extract values from
|
31
|
+
# @param [OM::XML::Term] term corresponding to desired xml values
|
32
|
+
# @param [Hash] (optional) solr_doc (values hash) to populate
|
33
|
+
def solrize_term(doc, term, solr_doc = Hash.new, field_mapper = nil, opts={})
|
34
|
+
parents = opts.fetch(:parents, [])
|
35
|
+
term_pointer = parents+[term.name]
|
36
|
+
nodeset = doc.term_values(*term_pointer)
|
37
|
+
|
38
|
+
nodeset.each do |n|
|
39
|
+
doc.solrize_node(n, term_pointer, term, solr_doc, field_mapper)
|
40
|
+
unless term.kind_of? OM::XML::NamedTermProxy
|
41
|
+
term.children.each_pair do |child_term_name, child_term|
|
42
|
+
doc.solrize_term(child_term, solr_doc, field_mapper, opts={:parents=>parents+[{term.name=>nodeset.index(n)}]})
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
solr_doc
|
47
|
+
end
|
48
|
+
|
49
|
+
# Populate a solr document with solr fields corresponding to the given xml node
|
50
|
+
# Field names are generated using settings from the term in the +doc+'s terminology corresponding to +term_pointer+
|
51
|
+
# If the supplied term does not have an index_as attribute, no indexing will be performed.
|
52
|
+
# @param [Nokogiri::XML::Node] node to solrize
|
53
|
+
# @param [OM::XML::Document] doc document the node came from
|
54
|
+
# @param [Array] term_pointer Array pointing to the term that should be used for solrization settings
|
55
|
+
# @param [Term] term the term to be solrized
|
56
|
+
# @param [Hash] (optional) solr_doc (values hash) to populate
|
57
|
+
# @return [Hash] the solr doc
|
58
|
+
def solrize_node(node_value, doc, term_pointer, term, solr_doc = Hash.new, field_mapper = nil, opts = {})
|
59
|
+
return solr_doc unless term.index_as && !term.index_as.empty?
|
60
|
+
|
61
|
+
generic_field_name_base = OM::XML::Terminology.term_generic_name(*term_pointer)
|
62
|
+
create_and_insert_terms(generic_field_name_base, node_value, term.index_as, solr_doc)
|
63
|
+
|
64
|
+
if term_pointer.length > 1
|
65
|
+
hierarchical_field_name_base = OM::XML::Terminology.term_hierarchical_name(*term_pointer)
|
66
|
+
create_and_insert_terms(hierarchical_field_name_base, node_value, term.index_as, solr_doc)
|
67
|
+
end
|
68
|
+
solr_doc
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
# Instance Methods
|
75
|
+
|
76
|
+
attr_accessor :field_mapper
|
77
|
+
|
78
|
+
def to_solr(solr_doc = Hash.new, field_mapper = self.field_mapper) # :nodoc:
|
79
|
+
self.class.solrize(self, solr_doc, field_mapper)
|
80
|
+
end
|
81
|
+
|
82
|
+
def solrize_term(term, solr_doc = Hash.new, field_mapper = self.field_mapper, opts={})
|
83
|
+
self.class.solrize_term(self, term, solr_doc, field_mapper, opts)
|
84
|
+
end
|
85
|
+
|
86
|
+
def solrize_node(node, term_pointer, term, solr_doc = Hash.new, field_mapper = self.field_mapper, opts={})
|
87
|
+
self.class.solrize_node(node, self, term_pointer, term, solr_doc, field_mapper, opts)
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
data/lib/om/xml/validation.rb
CHANGED
@@ -1,60 +1,60 @@
|
|
1
1
|
module OM::XML::Validation
|
2
2
|
extend ActiveSupport::Concern
|
3
|
-
|
4
|
-
# Class Methods -- These methods will be available on classes that include this Module
|
5
|
-
|
3
|
+
|
4
|
+
# Class Methods -- These methods will be available on classes that include this Module
|
5
|
+
|
6
6
|
module ClassMethods
|
7
7
|
attr_accessor :schema_url
|
8
8
|
attr_writer :schema_file
|
9
|
-
|
9
|
+
|
10
10
|
##
|
11
11
|
# Validation Support
|
12
12
|
##
|
13
|
-
|
13
|
+
|
14
14
|
# Validate the given document against the Schema provided by the root_property for this class
|
15
15
|
def validate(doc)
|
16
16
|
schema.validate(doc).each do |error|
|
17
17
|
puts error.message
|
18
18
|
end
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
# Retrieve the Nokogiri Schema for this class
|
22
22
|
def schema
|
23
23
|
@schema ||= Nokogiri::XML::Schema(schema_file.read)
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
# Retrieve the schema file for this class
|
27
27
|
# If the schema file is not already set, it will be loaded from the schema url provided in the root_property configuration for the class
|
28
28
|
def schema_file
|
29
29
|
@schema_file ||= file_from_url(schema_url)
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
# Retrieve file from a url (used by schema_file method to retrieve schema file from the schema url)
|
33
33
|
def file_from_url( url )
|
34
34
|
# parsed_url = URI.parse( url )
|
35
|
-
#
|
36
|
-
# if parsed_url.class != URI::HTTP
|
35
|
+
#
|
36
|
+
# if parsed_url.class != URI::HTTP
|
37
37
|
# raise "Invalid URL. Could not parse #{url} as a HTTP url."
|
38
38
|
# end
|
39
|
-
|
40
|
-
|
39
|
+
|
40
|
+
begin
|
41
41
|
file = open( url )
|
42
42
|
return file
|
43
43
|
rescue OpenURI::HTTPError => e
|
44
44
|
raise "Could not retrieve file from #{url}. Error: #{e}"
|
45
|
-
rescue Exception => e
|
45
|
+
rescue Exception => e
|
46
46
|
raise "Could not retrieve file from #{url}. Error: #{e}"
|
47
|
-
|
47
|
+
end
|
48
48
|
end
|
49
|
-
|
49
|
+
|
50
50
|
private :file_from_url
|
51
|
-
|
51
|
+
|
52
52
|
end
|
53
|
-
|
53
|
+
|
54
54
|
# Instance Methods -- These methods will be available on instances of classes that include this module
|
55
|
-
|
55
|
+
|
56
56
|
def validate
|
57
57
|
self.class.validate(self)
|
58
58
|
end
|
59
|
-
|
59
|
+
|
60
60
|
end
|
data/lib/om/xml/vocabulary.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
class OM::XML::Vocabulary
|
2
|
-
|
2
|
+
|
3
3
|
attr_accessor :builder
|
4
|
-
# Vocabularies are not editable once they've been created because inserting/removing/rearranging mappers in a vocabulary
|
4
|
+
# Vocabularies are not editable once they've been created because inserting/removing/rearranging mappers in a vocabulary
|
5
5
|
# will invalidate the xpath queries for an entire branch of the Vocabulary's tree of mappers.
|
6
6
|
# If you want to change a vocabulary's structure, retrieve it's +builder+, make your changes, and re-generate the vocabulary.
|
7
|
-
#
|
7
|
+
#
|
8
8
|
# Ex:
|
9
9
|
# builder = vocabulary.builder
|
10
10
|
# builder.insert_mapper(:name_, :namePart)
|
11
11
|
# vocabulary = builder.build
|
12
|
-
|
12
|
+
|
13
13
|
# Mappers can be retrieved by their mapper name
|
14
14
|
# Ex.
|
15
15
|
# vocabulary.retrieve_mapper(:name_, :namePart)
|
data/lib/tasks/om.rake
CHANGED
@@ -6,18 +6,20 @@ end
|
|
6
6
|
|
7
7
|
|
8
8
|
desc "Execute specs with coverage"
|
9
|
-
task :coverage do
|
9
|
+
task :coverage do
|
10
10
|
# Put spec opts in a file named .rspec in root
|
11
11
|
ruby_engine = defined?(RUBY_ENGINE) ? RUBY_ENGINE : "ruby"
|
12
12
|
ENV['COVERAGE'] = 'true' unless ruby_engine == 'jruby'
|
13
|
+
|
14
|
+
|
13
15
|
Rake::Task['om:rspec'].invoke
|
14
16
|
end
|
15
17
|
|
16
|
-
namespace :om do
|
18
|
+
namespace :om do
|
17
19
|
|
18
20
|
require 'rspec/core/rake_task'
|
19
21
|
RSpec::Core::RakeTask.new(:rspec) do |spec|
|
20
|
-
if ENV['COVERAGE']
|
22
|
+
if ENV['COVERAGE'] and RUBY_VERSION =~ /^1.8/
|
21
23
|
spec.rcov = true
|
22
24
|
spec.rcov_opts = %w{-I../../app -I../../lib --exclude spec\/*,gems\/*,ruby\/* --aggregate coverage.data}
|
23
25
|
end
|
@@ -33,7 +35,7 @@ namespace :om do
|
|
33
35
|
YARD::Rake::YardocTask.new(:doc) do |yt|
|
34
36
|
readme_filename = 'README.textile'
|
35
37
|
textile_docs = []
|
36
|
-
Dir[File.join(project_root, "*.textile")].each_with_index do |f, index|
|
38
|
+
Dir[File.join(project_root, "*.textile")].each_with_index do |f, index|
|
37
39
|
unless f.include?("/#{readme_filename}") # Skip readme, which is already built by the --readme option
|
38
40
|
textile_docs << '-'
|
39
41
|
textile_docs << f
|
data/om.gemspec
CHANGED
@@ -14,10 +14,11 @@ Gem::Specification.new do |s|
|
|
14
14
|
|
15
15
|
s.add_dependency 'activesupport'
|
16
16
|
s.add_dependency 'activemodel'
|
17
|
+
s.add_dependency 'solrizer', '~> 3.0.0.pre8'
|
17
18
|
s.add_dependency('nokogiri', ">= 1.4.2")
|
18
19
|
s.add_dependency('mediashelf-loggable')
|
19
20
|
s.add_dependency('deprecation')
|
20
|
-
s.add_development_dependency "rspec", "~> 2.
|
21
|
+
s.add_development_dependency "rspec", "~> 2.0"
|
21
22
|
s.add_development_dependency "rake"
|
22
23
|
s.add_development_dependency "rdoc"
|
23
24
|
s.add_development_dependency "awesome_print"
|
@@ -0,0 +1,90 @@
|
|
1
|
+
module Samples
|
2
|
+
class ModsArticle
|
3
|
+
|
4
|
+
include OM::XML::Document
|
5
|
+
|
6
|
+
set_terminology do |t|
|
7
|
+
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")
|
8
|
+
|
9
|
+
|
10
|
+
t.title_info(:path=>"titleInfo") {
|
11
|
+
t.main_title(:index_as=>[:facetable],:path=>"title", :label=>"title") {
|
12
|
+
t.main_title_lang(:path=>{:attribute=> "xml:lang"})
|
13
|
+
}
|
14
|
+
t.french_title(:ref=>[:title_info,:main_title], :attributes=>{"xml:lang"=>"fre"})
|
15
|
+
|
16
|
+
t.language(:index_as=>[:facetable, :stored_searchable],:path=>{:attribute=>"lang"})
|
17
|
+
}
|
18
|
+
t.language{
|
19
|
+
t.lang_code(:index_as=>[:facetable], :path=>"languageTerm", :attributes=>{:type=>"code"})
|
20
|
+
}
|
21
|
+
t.abstract(:index_as=>[:stored_searchable])
|
22
|
+
t.subject {
|
23
|
+
t.topic(:index_as=>[:facetable])
|
24
|
+
}
|
25
|
+
t.topic_tag(:proxy=>[:subject, :topic], :index_as=>[:stored_searchable])
|
26
|
+
# t.topic_tag(:index_as=>[:facetable],:path=>"subject", :default_content_path=>"topic")
|
27
|
+
# This is a mods:name. The underscore is purely to avoid namespace conflicts.
|
28
|
+
t.name_ {
|
29
|
+
# this is a namepart
|
30
|
+
t.namePart(:type=>:string, :label=>"generic name")
|
31
|
+
# affiliations are great
|
32
|
+
t.affiliation
|
33
|
+
t.institution(:path=>"affiliation", :index_as=>[:facetable], :label=>"organization")
|
34
|
+
t.displayForm
|
35
|
+
t.role(:ref=>[:role])
|
36
|
+
t.description(:index_as=>[:facetable])
|
37
|
+
t.date(:path=>"namePart", :attributes=>{:type=>"date"})
|
38
|
+
t.last_name(:path=>"namePart", :attributes=>{:type=>"family"}, :index_as=>[:stored_searchable])
|
39
|
+
t.first_name(:path=>"namePart", :attributes=>{:type=>"given"}, :label=>"first name")
|
40
|
+
t.terms_of_address(:path=>"namePart", :attributes=>{:type=>"termsOfAddress"})
|
41
|
+
t.computing_id
|
42
|
+
t.name_content(:path=>"text()")
|
43
|
+
}
|
44
|
+
# lookup :person, :first_name
|
45
|
+
t.person(:ref=>:name, :attributes=>{:type=>"personal"}, :index_as=>[:facetable])
|
46
|
+
t.department(:proxy=>[:person,:description],:index_as=>[:facetable])
|
47
|
+
t.organization(:ref=>:name, :attributes=>{:type=>"corporate"}, :index_as=>[:facetable])
|
48
|
+
t.conference(:ref=>:name, :attributes=>{:type=>"conference"}, :index_as=>[:facetable])
|
49
|
+
t.role {
|
50
|
+
t.text(:path=>"roleTerm",:attributes=>{:type=>"text"}, :index_as=>[:stored_searchable])
|
51
|
+
t.code(:path=>"roleTerm",:attributes=>{:type=>"code"})
|
52
|
+
}
|
53
|
+
t.journal(:path=>'relatedItem', :attributes=>{:type=>"host"}) {
|
54
|
+
t.title_info(:index_as=>[:facetable],:ref=>[:title_info])
|
55
|
+
t.origin_info(:path=>"originInfo") {
|
56
|
+
t.publisher
|
57
|
+
t.date_issued(:path=>"dateIssued", :type => :date, :index_as => [:stored_searchable])
|
58
|
+
t.issuance(:index_as=>[:facetable])
|
59
|
+
}
|
60
|
+
t.issn(:path=>"identifier", :attributes=>{:type=>"issn"})
|
61
|
+
t.issue(:path=>"part") {
|
62
|
+
t.volume(:path=>"detail", :attributes=>{:type=>"volume"}, :default_content_path=>"number")
|
63
|
+
t.level(:path=>"detail", :attributes=>{:type=>"number"}, :default_content_path=>"number")
|
64
|
+
t.extent
|
65
|
+
t.pages(:path=>"extent", :attributes=>{:unit=>"pages"}) {
|
66
|
+
t.start
|
67
|
+
t.end
|
68
|
+
}
|
69
|
+
t.start_page(:proxy=>[:pages, :start])
|
70
|
+
t.end_page(:proxy=>[:pages, :end])
|
71
|
+
t.publication_date(:path=>"date", :type => :date, :index_as => [:stored_searchable])
|
72
|
+
}
|
73
|
+
}
|
74
|
+
t.note
|
75
|
+
t.location(:path=>"location") {
|
76
|
+
t.url(:path=>"url")
|
77
|
+
}
|
78
|
+
t.publication_url(:proxy=>[:location,:url])
|
79
|
+
t.title(:proxy=>[:title_info, :main_title])
|
80
|
+
t.journal_title(:proxy=>[:journal, :title_info, :main_title])
|
81
|
+
t.pub_date(:proxy=>[:journal, :issue, :publication_date])
|
82
|
+
t.issue_date(:ref=>[:journal, :origin_info, :date_issued], :type=> :date)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Changes from OM::Properties implementation
|
86
|
+
# renamed family_name => last_name
|
87
|
+
# start_page & end_page now accessible as [:journal, :issue, :pages, :start] (etc.)
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|
@@ -71,7 +71,7 @@
|
|
71
71
|
</titleInfo>
|
72
72
|
<originInfo>
|
73
73
|
<publisher>PUBLISHER</publisher>
|
74
|
-
<dateIssued>
|
74
|
+
<dateIssued>2007-02-15</dateIssued>
|
75
75
|
</originInfo>
|
76
76
|
<identifier type="issn">0013-8908</identifier>
|
77
77
|
<part>
|
@@ -84,7 +84,7 @@
|
|
84
84
|
<extent unit="pages">
|
85
85
|
<start>195</start>
|
86
86
|
</extent>
|
87
|
-
<date>
|
87
|
+
<date>2007-02-01</date>
|
88
88
|
</part>
|
89
89
|
</relatedItem>
|
90
90
|
|
@@ -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
|
-
|
33
|
+
subject.relevant_container.the_thing_we_want.should == ["1", "2"]
|
34
34
|
end
|
35
35
|
|
36
36
|
it "should only pull out the_thing_we_want at the root level" do
|
37
|
-
|
37
|
+
subject.the_thing_we_want.should == ["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
|
-
|
56
|
+
subject.elementA.should == ["valA"]
|
57
57
|
end
|
58
58
|
|
59
59
|
it "should handle term paths" do
|
60
|
-
|
60
|
+
subject.elC.should == ["valC"]
|
61
61
|
end
|
62
62
|
|
63
63
|
it "should handle multiple-element, terms with paths correctly" do
|
64
|
-
|
64
|
+
subject.elB.should == ["valB1", "valB2"]
|
65
65
|
end
|
66
66
|
|
67
67
|
it "should handle terms that require specific attributes" do
|
68
|
-
|
68
|
+
subject.elementC.should == ["valC"]
|
69
69
|
end
|
70
70
|
|
71
71
|
it "should handle" do
|
72
|
-
|
73
|
-
|
72
|
+
subject.here.length.should == 1
|
73
|
+
subject.here.first.split(/\W/).should include('123', '456')
|
74
74
|
end
|
75
75
|
|
76
76
|
it "should handle missing terms" do
|
77
|
-
|
77
|
+
subject.there.should be_empty
|
78
78
|
end
|
79
79
|
|
80
80
|
it "should handle element value given the absence of a specific attribute" do
|
81
|
-
|
82
|
-
|
81
|
+
subject.elementD.should == ["valD1"]
|
82
|
+
subject.no_attrib.should == ["valB1"]
|
83
83
|
end
|
84
84
|
|
85
85
|
it "should handle OM terms for an attribute value" do
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
86
|
+
subject.elementB.my_attr.should == ["vole"]
|
87
|
+
subject.alternate.should == ["vole"]
|
88
|
+
subject.another.should == ["vole"]
|
89
|
+
subject.animal_attrib.should include("vole", "seagull")
|
90
90
|
end
|
91
91
|
end
|