linked_vocabs 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +191 -0
- data/README.md +27 -0
- data/Rakefile +17 -0
- data/lib/linked_vocabs.rb +75 -0
- data/lib/linked_vocabs/controlled.rb +199 -0
- data/lib/linked_vocabs/deep_fetch.rb +53 -0
- data/lib/linked_vocabs/validators.rb +7 -0
- data/lib/linked_vocabs/validators/authority_validator.rb +11 -0
- data/lib/linked_vocabs/validators/property_validator.rb +21 -0
- data/lib/linked_vocabs/version.rb +3 -0
- data/lib/linked_vocabs/vocabularies.rb +6 -0
- data/lib/rdf/dcmitype.rb +138 -0
- data/lib/rdf/geonames.rb +8 -0
- data/lib/rdf/lcsh.rb +8 -0
- data/linked_vocabs.gemspec +31 -0
- data/spec/controlled_spec.rb +170 -0
- data/spec/linked_vocabs_spec.rb +38 -0
- data/spec/property_validator_spec.rb +74 -0
- data/spec/spec_helper.rb +7 -0
- metadata +196 -0
@@ -0,0 +1,53 @@
|
|
1
|
+
module OregonDigital::RDF
|
2
|
+
module DeepFetch
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
def fetch_external
|
5
|
+
controlled_properties.each do |property|
|
6
|
+
get_values(property).each do |value|
|
7
|
+
resource = value.respond_to?(:resource) ? value.resource : value
|
8
|
+
next unless resource.kind_of?(ActiveFedora::Rdf::Resource)
|
9
|
+
fetch_value(resource) if resource.kind_of? ActiveFedora::Rdf::Resource
|
10
|
+
resource.persist! unless value.kind_of?(ActiveFedora::Base)
|
11
|
+
fix_fedora_index(property, resource)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def fix_fedora_index(property, resource)
|
17
|
+
# Get assets which have this property set, but don't have the right label.
|
18
|
+
if resource.rdf_label.first.blank? || resource.rdf_label.first.to_s == resource.rdf_subject.to_s
|
19
|
+
assets = ActiveFedora::Base.where("#{Solrizer.solr_name(apply_prefix(property), :facetable)}:#{RSolr.escape(resource.rdf_subject.to_s)} AND #{Solrizer.solr_name(apply_prefix("#{property}_label"), :facetable)}:[\"\" TO *]")
|
20
|
+
else
|
21
|
+
assets = ActiveFedora::Base.where(
|
22
|
+
Solrizer.solr_name(apply_prefix(property), :facetable) => resource.rdf_subject.to_s,
|
23
|
+
"-#{Solrizer.solr_name(apply_prefix("#{property}_label"), :facetable)}" => "#{resource.rdf_label.first}$#{resource.rdf_subject.to_s}"
|
24
|
+
)
|
25
|
+
end
|
26
|
+
assets.each do |a|
|
27
|
+
a.skip_queue = 1 if a.respond_to?(:skip_queue=)
|
28
|
+
a.update_index
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
protected
|
33
|
+
|
34
|
+
def controlled_properties
|
35
|
+
@controlled_properties ||= self.class.properties.each_with_object([]) do |(key, value), arr|
|
36
|
+
if value["class_name"] && (value["class_name"] < ActiveFedora::Rdf::Resource || value["class_name"].new.resource.class < ActiveFedora::Rdf::Resource)
|
37
|
+
arr << key
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def fetch_value(value)
|
43
|
+
redis_connection.cache("fetch-cache:#{value.rdf_subject.to_s}", 7.days) do
|
44
|
+
value.fetch
|
45
|
+
Time.current.to_s
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def redis_connection
|
50
|
+
@redis ||= Redis.new
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
require 'linked_vocabs/validators/authority_validator'
|
2
|
+
require 'linked_vocabs/validators/property_validator'
|
3
|
+
|
4
|
+
module LinkedVocabs::Validators
|
5
|
+
# autoload :AuthorityValidator, 'linked_vocabs/validators/authority_validator'
|
6
|
+
# autoload :PropertyValidator, 'linked_vocabs/validators/property_validator'
|
7
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'active_model'
|
2
|
+
|
3
|
+
module LinkedVocabs::Validators
|
4
|
+
class AuthorityValidator < ActiveModel::Validator
|
5
|
+
def validate(record)
|
6
|
+
unless record.in_vocab?
|
7
|
+
record.errors.add :base, "#{record.rdf_subject.to_s} is not a term in a controlled vocabulary #{record.class.vocabularies}"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'active_model'
|
2
|
+
|
3
|
+
module LinkedVocabs::Validators
|
4
|
+
class PropertyValidator < ActiveModel::EachValidator
|
5
|
+
def validate_each(record, attribute, values)
|
6
|
+
values.each do |v|
|
7
|
+
unless v.try(:in_vocab?)
|
8
|
+
term = v.try(:rdf_subject) || v
|
9
|
+
vocabularies = record.class.properties[attribute].class_name.vocabularies.keys
|
10
|
+
record.errors.add :base, "value `#{term} for `#{attribute}` property is not a term in a controlled vocabulary #{vocabularies.join(', ')}"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module ActiveModel::Validations::HelperMethods
|
18
|
+
def validates_vocabulary_of(*attr_names)
|
19
|
+
validates_with LinkedVocabs::Validators::PropertyValidator, :attributes => attr_names
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,6 @@
|
|
1
|
+
module LinkedVocabs::Vocabularies
|
2
|
+
autoload :DCMITYPE, 'linked_vocabs/vocabularies/dcmitype'
|
3
|
+
autoload :GEONAMES, 'linked_vocabs/vocabularies/geonames'
|
4
|
+
autoload :LCSH, 'linked_vocabs/vocabularies/lcsh'
|
5
|
+
autoload :ISO_630_2, 'linked_vocabs/vocabularies/iso_639_2'
|
6
|
+
end
|
data/lib/rdf/dcmitype.rb
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
# This file generated automatically using vocab-fetch from http://dublincore.org/2012/06/14/dctype.rdf
|
3
|
+
require 'rdf'
|
4
|
+
module RDF
|
5
|
+
class DCMITYPE < RDF::StrictVocabulary("http://purl.org/dc/dcmitype/")
|
6
|
+
|
7
|
+
# Class definitions
|
8
|
+
term :Collection,
|
9
|
+
comment: %(An aggregation of resources.).freeze,
|
10
|
+
"dc:description" => %(A collection is described as a group; its parts may also be separately described.).freeze,
|
11
|
+
"dc:hasVersion" => %(http://dublincore.org/usage/terms/history/#Collection-003).freeze,
|
12
|
+
"dc:issued" => %(2000-07-11).freeze,
|
13
|
+
"dc:modified" => %(2008-01-14).freeze,
|
14
|
+
"http://purl.org/dc/dcam/memberOf" => %(dc:DCMIType).freeze,
|
15
|
+
label: "Collection".freeze,
|
16
|
+
"rdfs:isDefinedBy" => %(dcmitype:).freeze,
|
17
|
+
type: "rdfs:Class".freeze
|
18
|
+
term :Dataset,
|
19
|
+
comment: %(Data encoded in a defined structure.).freeze,
|
20
|
+
"dc:description" => %(Examples include lists, tables, and databases. A dataset may be useful for direct machine processing.).freeze,
|
21
|
+
"dc:hasVersion" => %(http://dublincore.org/usage/terms/history/#Dataset-003).freeze,
|
22
|
+
"dc:issued" => %(2000-07-11).freeze,
|
23
|
+
"dc:modified" => %(2008-01-14).freeze,
|
24
|
+
"http://purl.org/dc/dcam/memberOf" => %(dc:DCMIType).freeze,
|
25
|
+
label: "Dataset".freeze,
|
26
|
+
"rdfs:isDefinedBy" => %(dcmitype:).freeze,
|
27
|
+
type: "rdfs:Class".freeze
|
28
|
+
term :Event,
|
29
|
+
comment: %(A non-persistent, time-based occurrence.).freeze,
|
30
|
+
"dc:description" => %(Metadata for an event provides descriptive information that is the basis for discovery of the purpose, location, duration, and responsible agents associated with an event. Examples include an exhibition, webcast, conference, workshop, open day, performance, battle, trial, wedding, tea party, conflagration.).freeze,
|
31
|
+
"dc:hasVersion" => %(http://dublincore.org/usage/terms/history/#Event-003).freeze,
|
32
|
+
"dc:issued" => %(2000-07-11).freeze,
|
33
|
+
"dc:modified" => %(2008-01-14).freeze,
|
34
|
+
"http://purl.org/dc/dcam/memberOf" => %(dc:DCMIType).freeze,
|
35
|
+
label: "Event".freeze,
|
36
|
+
"rdfs:isDefinedBy" => %(dcmitype:).freeze,
|
37
|
+
type: "rdfs:Class".freeze
|
38
|
+
term :Image,
|
39
|
+
comment: %(A visual representation other than text.).freeze,
|
40
|
+
"dc:description" => %(Examples include images and photographs of physical objects, paintings, prints, drawings, other images and graphics, animations and moving pictures, film, diagrams, maps, musical notation. Note that Image may include both electronic and physical representations.).freeze,
|
41
|
+
"dc:hasVersion" => %(http://dublincore.org/usage/terms/history/#Image-004).freeze,
|
42
|
+
"dc:issued" => %(2000-07-11).freeze,
|
43
|
+
"dc:modified" => %(2008-01-14).freeze,
|
44
|
+
"http://purl.org/dc/dcam/memberOf" => %(dc:DCMIType).freeze,
|
45
|
+
label: "Image".freeze,
|
46
|
+
"rdfs:isDefinedBy" => %(dcmitype:).freeze,
|
47
|
+
type: "rdfs:Class".freeze
|
48
|
+
term :InteractiveResource,
|
49
|
+
comment: %(A resource requiring interaction from the user to be understood, executed, or experienced.).freeze,
|
50
|
+
"dc:description" => %(Examples include forms on Web pages, applets, multimedia learning objects, chat services, or virtual reality environments.).freeze,
|
51
|
+
"dc:hasVersion" => %(http://dublincore.org/usage/terms/history/#InteractiveResource-003).freeze,
|
52
|
+
"dc:issued" => %(2000-07-11).freeze,
|
53
|
+
"dc:modified" => %(2008-01-14).freeze,
|
54
|
+
"http://purl.org/dc/dcam/memberOf" => %(dc:DCMIType).freeze,
|
55
|
+
label: "Interactive Resource".freeze,
|
56
|
+
"rdfs:isDefinedBy" => %(dcmitype:).freeze,
|
57
|
+
type: "rdfs:Class".freeze
|
58
|
+
term :MovingImage,
|
59
|
+
comment: %(A series of visual representations imparting an impression of motion when shown in succession.).freeze,
|
60
|
+
"dc:description" => %(Examples include animations, movies, television programs, videos, zoetropes, or visual output from a simulation. Instances of the type Moving Image must also be describable as instances of the broader type Image.).freeze,
|
61
|
+
"dc:hasVersion" => %(http://dublincore.org/usage/terms/history/#MovingImage-003).freeze,
|
62
|
+
"dc:issued" => %(2003-11-18).freeze,
|
63
|
+
"dc:modified" => %(2008-01-14).freeze,
|
64
|
+
"http://purl.org/dc/dcam/memberOf" => %(dc:DCMIType).freeze,
|
65
|
+
label: "Moving Image".freeze,
|
66
|
+
"rdfs:isDefinedBy" => %(dcmitype:).freeze,
|
67
|
+
subClassOf: "dcmitype:Image".freeze,
|
68
|
+
type: "rdfs:Class".freeze
|
69
|
+
term :PhysicalObject,
|
70
|
+
comment: %(An inanimate, three-dimensional object or substance.).freeze,
|
71
|
+
"dc:description" => %(Note that digital representations of, or surrogates for, these objects should use Image, Text or one of the other types.).freeze,
|
72
|
+
"dc:hasVersion" => %(http://dublincore.org/usage/terms/history/#PhysicalObject-003).freeze,
|
73
|
+
"dc:issued" => %(2002-07-13).freeze,
|
74
|
+
"dc:modified" => %(2008-01-14).freeze,
|
75
|
+
"http://purl.org/dc/dcam/memberOf" => %(dc:DCMIType).freeze,
|
76
|
+
label: "Physical Object".freeze,
|
77
|
+
"rdfs:isDefinedBy" => %(dcmitype:).freeze,
|
78
|
+
type: "rdfs:Class".freeze
|
79
|
+
term :Service,
|
80
|
+
comment: %(A system that provides one or more functions.).freeze,
|
81
|
+
"dc:description" => %(Examples include a photocopying service, a banking service, an authentication service, interlibrary loans, a Z39.50 or Web server.).freeze,
|
82
|
+
"dc:hasVersion" => %(http://dublincore.org/usage/terms/history/#Service-003).freeze,
|
83
|
+
"dc:issued" => %(2000-07-11).freeze,
|
84
|
+
"dc:modified" => %(2008-01-14).freeze,
|
85
|
+
"http://purl.org/dc/dcam/memberOf" => %(dc:DCMIType).freeze,
|
86
|
+
label: "Service".freeze,
|
87
|
+
"rdfs:isDefinedBy" => %(dcmitype:).freeze,
|
88
|
+
type: "rdfs:Class".freeze
|
89
|
+
term :Software,
|
90
|
+
comment: %(A computer program in source or compiled form.).freeze,
|
91
|
+
"dc:description" => %(Examples include a C source file, MS-Windows .exe executable, or Perl script.).freeze,
|
92
|
+
"dc:hasVersion" => %(http://dublincore.org/usage/terms/history/#Software-003).freeze,
|
93
|
+
"dc:issued" => %(2000-07-11).freeze,
|
94
|
+
"dc:modified" => %(2008-01-14).freeze,
|
95
|
+
"http://purl.org/dc/dcam/memberOf" => %(dc:DCMIType).freeze,
|
96
|
+
label: "Software".freeze,
|
97
|
+
"rdfs:isDefinedBy" => %(dcmitype:).freeze,
|
98
|
+
type: "rdfs:Class".freeze
|
99
|
+
term :Sound,
|
100
|
+
comment: %(A resource primarily intended to be heard.).freeze,
|
101
|
+
"dc:description" => %(Examples include a music playback file format, an audio compact disc, and recorded speech or sounds.).freeze,
|
102
|
+
"dc:hasVersion" => %(http://dublincore.org/usage/terms/history/#Sound-003).freeze,
|
103
|
+
"dc:issued" => %(2000-07-11).freeze,
|
104
|
+
"dc:modified" => %(2008-01-14).freeze,
|
105
|
+
"http://purl.org/dc/dcam/memberOf" => %(dc:DCMIType).freeze,
|
106
|
+
label: "Sound".freeze,
|
107
|
+
"rdfs:isDefinedBy" => %(dcmitype:).freeze,
|
108
|
+
type: "rdfs:Class".freeze
|
109
|
+
term :StillImage,
|
110
|
+
comment: %(A static visual representation.).freeze,
|
111
|
+
"dc:description" => %(Examples include paintings, drawings, graphic designs, plans and maps. Recommended best practice is to assign the type Text to images of textual materials. Instances of the type Still Image must also be describable as instances of the broader type Image.).freeze,
|
112
|
+
"dc:hasVersion" => %(http://dublincore.org/usage/terms/history/#StillImage-003).freeze,
|
113
|
+
"dc:issued" => %(2003-11-18).freeze,
|
114
|
+
"dc:modified" => %(2008-01-14).freeze,
|
115
|
+
"http://purl.org/dc/dcam/memberOf" => %(dc:DCMIType).freeze,
|
116
|
+
label: "Still Image".freeze,
|
117
|
+
"rdfs:isDefinedBy" => %(dcmitype:).freeze,
|
118
|
+
subClassOf: "dcmitype:Image".freeze,
|
119
|
+
type: "rdfs:Class".freeze
|
120
|
+
term :Text,
|
121
|
+
comment: %(A resource consisting primarily of words for reading.).freeze,
|
122
|
+
"dc:description" => %(Examples include books, letters, dissertations, poems, newspapers, articles, archives of mailing lists. Note that facsimiles or images of texts are still of the genre Text.).freeze,
|
123
|
+
"dc:hasVersion" => %(http://dublincore.org/usage/terms/history/#Text-003).freeze,
|
124
|
+
"dc:issued" => %(2000-07-11).freeze,
|
125
|
+
"dc:modified" => %(2008-01-14).freeze,
|
126
|
+
"http://purl.org/dc/dcam/memberOf" => %(dc:DCMIType).freeze,
|
127
|
+
label: "Text".freeze,
|
128
|
+
"rdfs:isDefinedBy" => %(dcmitype:).freeze,
|
129
|
+
type: "rdfs:Class".freeze
|
130
|
+
|
131
|
+
# Extra definitions
|
132
|
+
term :"",
|
133
|
+
"dc:modified" => %(2012-06-14).freeze,
|
134
|
+
"dc:publisher" => %(http://purl.org/dc/aboutdcmi#DCMI).freeze,
|
135
|
+
"dc:title" => %(DCMI Type Vocabulary).freeze,
|
136
|
+
label: "".freeze
|
137
|
+
end
|
138
|
+
end
|
data/lib/rdf/geonames.rb
ADDED
data/lib/rdf/lcsh.rb
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
# This file generated automatically using vocab-fetch from http://id.loc.gov/authorities/subjects/
|
3
|
+
require 'rdf'
|
4
|
+
module RDF
|
5
|
+
class LCSH < RDF::Vocabulary("http://id.loc.gov/authorities/subjects/")
|
6
|
+
# terms not fetched by vocab-fetch
|
7
|
+
end
|
8
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'linked_vocabs/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "linked_vocabs"
|
8
|
+
spec.version = LinkedVocabs::VERSION
|
9
|
+
spec.authors = ["Tom Johnson"]
|
10
|
+
spec.email = ["johnson.tom@gmail.com"]
|
11
|
+
spec.description = 'Linked Data Controlled Vocabularies for ActiveFedora::Rdf.'
|
12
|
+
spec.summary = 'Linked Data Controlled Vocabularies for ActiveFedora::Rdf.'
|
13
|
+
spec.license = "APACHE2"
|
14
|
+
|
15
|
+
spec.files = `git ls-files`.split($/)
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_development_dependency "bundler"
|
21
|
+
spec.add_development_dependency "rspec"
|
22
|
+
spec.add_development_dependency "guard"
|
23
|
+
spec.add_development_dependency "guard-rspec"
|
24
|
+
|
25
|
+
spec.add_dependency 'rake'
|
26
|
+
spec.add_dependency 'active-triples', '>=0.1.0'
|
27
|
+
spec.add_dependency 'rdf', '>=1.1.2.1'
|
28
|
+
spec.add_dependency 'sparql'
|
29
|
+
spec.add_dependency 'sparql-client'
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,170 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe LinkedVocabs::Controlled do
|
4
|
+
before(:each) do
|
5
|
+
ActiveTriples::Repositories.add_repository :default, RDF::Repository.new
|
6
|
+
class DummyAuthority < ActiveTriples::Resource
|
7
|
+
include LinkedVocabs::Controlled
|
8
|
+
configure :repository => :default
|
9
|
+
use_vocabulary :dcmitype
|
10
|
+
property :title, :predicate => RDF::DC.title
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
after(:each) do
|
15
|
+
Object.send(:remove_const, 'DummyAuthority') if Object
|
16
|
+
ActiveTriples::Repositories.clear_repositories!
|
17
|
+
end
|
18
|
+
|
19
|
+
subject { DummyAuthority }
|
20
|
+
|
21
|
+
describe 'vocabulary registration' do
|
22
|
+
it 'should add vocabulary' do
|
23
|
+
expect(subject.vocabularies).to include :dcmitype
|
24
|
+
end
|
25
|
+
it 'should find its vocabulary class' do
|
26
|
+
expect(subject.vocabularies[:dcmitype][:class]).to eq RDF::DCMITYPE
|
27
|
+
end
|
28
|
+
it 'should allow multiple vocabularies' do
|
29
|
+
subject.use_vocabulary :lcsh
|
30
|
+
expect(subject.vocabularies).to include :dcmitype, :lcsh
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '#list_terms' do
|
35
|
+
it 'should list terms from registered StrictVocabs' do
|
36
|
+
subject.vocabularies.each do |name, vocab|
|
37
|
+
expect([vocab[:class].Image] - subject.list_terms).to be_empty
|
38
|
+
end
|
39
|
+
end
|
40
|
+
it 'should list only terms from registered StrictVocabs' do
|
41
|
+
terms = []
|
42
|
+
subject.vocabularies.each do |name, vocab|
|
43
|
+
terms += vocab[:class].properties
|
44
|
+
end
|
45
|
+
expect(subject.list_terms - terms).to be_empty
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe '#rdf_label' do
|
50
|
+
subject {DummyAuthority.new}
|
51
|
+
context "when there are only plain labels" do
|
52
|
+
before do
|
53
|
+
subject.title = ["English", "French"]
|
54
|
+
end
|
55
|
+
it "should return both" do
|
56
|
+
expect(subject.title).to eq ["English", "French"]
|
57
|
+
end
|
58
|
+
end
|
59
|
+
# context "when there are english labels" do
|
60
|
+
# before do
|
61
|
+
# subject.title = RDF::Literal.new("English", :langauge => :en)
|
62
|
+
# end
|
63
|
+
# context "and plain labels" do
|
64
|
+
# before do
|
65
|
+
# subject.title = ["Plain", RDF::Literal.new("English", :language => :en)]
|
66
|
+
# end
|
67
|
+
# it "should return the english label" do
|
68
|
+
# expect(subject.rdf_label).to eq ["English"]
|
69
|
+
# end
|
70
|
+
# end
|
71
|
+
# context "and other language labels" do
|
72
|
+
# before do
|
73
|
+
# subject.title = [RDF::Literal.new("French", :language => :fr), RDF::Literal.new("English", :language => :en)]
|
74
|
+
# end
|
75
|
+
# it "should return the english label" do
|
76
|
+
# expect(subject.rdf_label).to eq ["English"]
|
77
|
+
# end
|
78
|
+
# end
|
79
|
+
# end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe '#load_vocabularies' do
|
83
|
+
it 'should load data' do
|
84
|
+
subject.load_vocabularies
|
85
|
+
expect(subject.new('Image').has_subject?(RDF::URI('http://purl.org/dc/dcmitype/Image'))).to be_true
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe '#search' do
|
90
|
+
before do
|
91
|
+
image = subject.new('Image')
|
92
|
+
image << RDF::Statement(image.rdf_subject, RDF::SKOS.prefLabel, "Image")
|
93
|
+
image.persist!
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'should return matches' do
|
97
|
+
expect(subject.new.search('Image').first[:id]).to eq RDF::URI('http://purl.org/dc/dcmitype/Image')
|
98
|
+
end
|
99
|
+
it 'should search case insensitively' do
|
100
|
+
expect(subject.new.search('ima').first[:id]).to eq RDF::URI('http://purl.org/dc/dcmitype/Image')
|
101
|
+
end
|
102
|
+
describe 'non-label matches' do
|
103
|
+
before do
|
104
|
+
doc = subject.new('Text')
|
105
|
+
doc << RDF::Statement(doc.rdf_subject, RDF::DC.description, "This is not an image!")
|
106
|
+
doc.persist!
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'should return non-label matches if no label matches exist' do
|
110
|
+
image = subject.new('Image')
|
111
|
+
image.clear
|
112
|
+
image.persist!
|
113
|
+
expect(subject.new.search('ima').map { |result| result[:id] } ).to include subject.new('Text').rdf_subject
|
114
|
+
end
|
115
|
+
it 'should not return non-label matches if label matches exist' do
|
116
|
+
expect(subject.new.search('ima').map { |result| result[:id] } ).not_to include subject.new('Text').rdf_subject
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe 'uris' do
|
122
|
+
it 'should use a vocabulary uri' do
|
123
|
+
dummy = DummyAuthority.new('Image')
|
124
|
+
expect(dummy.rdf_subject).to eq RDF::DCMITYPE.Image
|
125
|
+
end
|
126
|
+
it 'should accept a full uri' do
|
127
|
+
dummy = DummyAuthority.new(RDF::DCMITYPE.Image)
|
128
|
+
expect(dummy.rdf_subject).to eq RDF::DCMITYPE.Image
|
129
|
+
end
|
130
|
+
it 'should accept a string for a full uri' do
|
131
|
+
dummy = DummyAuthority.new(RDF::DCMITYPE.Image.to_s)
|
132
|
+
expect(dummy.rdf_subject).to eq RDF::DCMITYPE.Image
|
133
|
+
end
|
134
|
+
it 'raises an error if the term is not in the vocabulary' do
|
135
|
+
expect{ DummyAuthority.new('FakeTerm') }.to raise_error
|
136
|
+
end
|
137
|
+
it 'is invalid if the uri is not in the vocabulary' do
|
138
|
+
d = DummyAuthority.new(RDF::URI('http://example.org/blah'))
|
139
|
+
expect(d).not_to be_valid
|
140
|
+
end
|
141
|
+
it 'is invalid if the uri string is not in the vocabulary' do
|
142
|
+
d = DummyAuthority.new('http://example.org/blah')
|
143
|
+
expect(d).not_to be_valid
|
144
|
+
end
|
145
|
+
it 'is invalid if the uri string is not in the strict vocabulary but has vocab prefix' do
|
146
|
+
d = DummyAuthority.new(subject.vocabularies[:dcmitype][:prefix] + 'FakeTerm')
|
147
|
+
expect(d).not_to be_valid
|
148
|
+
end
|
149
|
+
it 'should raise an error if the uri string just the prefix' do
|
150
|
+
d = DummyAuthority.new(subject.vocabularies[:dcmitype][:prefix])
|
151
|
+
expect(d).not_to be_valid
|
152
|
+
end
|
153
|
+
|
154
|
+
context 'with non-strict vocabularies' do
|
155
|
+
before(:each) do
|
156
|
+
DummyAuthority.use_vocabulary :geonames
|
157
|
+
end
|
158
|
+
it 'should make uri for terms not defined' do
|
159
|
+
expect(DummyAuthority.new('http://sws.geonames.org/FakeTerm').rdf_subject).to eq RDF::GEONAMES.FakeTerm
|
160
|
+
p end
|
161
|
+
it 'should use strict uri when one is available' do
|
162
|
+
expect(DummyAuthority.new('Image').rdf_subject).to eq RDF::DCMITYPE.Image
|
163
|
+
end
|
164
|
+
it 'should raise error for terms that are not clear' do
|
165
|
+
DummyAuthority.use_vocabulary :lcsh
|
166
|
+
expect{ DummyAuthority.new('FakeTerm').rdf_subject }.to raise_error
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|