qa 0.7.0 → 0.8.0
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.
- checksums.yaml +4 -4
- data/README.md +40 -1
- data/config/initializers/authorities.rb +3 -1
- data/lib/generators/qa/local/files/files_generator.rb +10 -0
- data/lib/generators/qa/local/tables/tables_generator.rb +19 -0
- data/lib/generators/qa/local/tables/templates/add_index_to_local_authorities.rb +6 -0
- data/lib/qa/authorities/geonames.rb +11 -2
- data/lib/qa/authorities/local.rb +29 -52
- data/lib/qa/authorities/local/registry.rb +52 -0
- data/lib/qa/authorities/local/table_based_authority.rb +53 -0
- data/lib/qa/version.rb +1 -1
- data/spec/lib/authorities/assign_fast_spec.rb +2 -2
- data/spec/lib/authorities/file_based_authority_spec.rb +1 -1
- data/spec/lib/authorities/geonames_spec.rb +29 -6
- data/spec/lib/authorities/getty_spec.rb +3 -3
- data/spec/lib/authorities/loc_spec.rb +2 -2
- data/spec/lib/authorities/local_spec.rb +46 -3
- data/spec/lib/authorities/table_based_authority_spec.rb +67 -0
- data/spec/test_app_templates/lib/generators/test_app_generator.rb +2 -1
- metadata +9 -6
- data/lib/generators/qa/local/local_generator.rb +0 -9
- data/lib/qa/authorities/local_subauthority.rb +0 -21
- data/spec/lib/authorities_local_subauthorities_spec.rb +0 -51
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 04f7b6155dd96973d581100cf2a1dd4a3d354a9e
|
4
|
+
data.tar.gz: fb7def7c149256be271a7b95de1d784f089218f7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0a19a175ac1cb3b84fd9af171a426229bf0b757c3daf5a1f76dd95fc6074ed8950f233d97aaaeba0d127f0e0eb7e7fedbeb304f530abf82036a1947d0a46b71a
|
7
|
+
data.tar.gz: 52cea5dc60f4758990f9bc8c73652c1f7396abd9d3b894d0357ae912e794f9e526a8ef2cfa35ead7aca8129a1c16611541fc0fdb1029e1c02cb30754b7b04bc1
|
data/README.md
CHANGED
@@ -166,11 +166,12 @@ Qa::Authorities::Geonames.username = 'myAccountName'
|
|
166
166
|
|
167
167
|
### Local Authorities
|
168
168
|
|
169
|
+
#### In YAML files
|
169
170
|
For simple use cases when you have a few terms that don't change very often.
|
170
171
|
|
171
172
|
Run the generator to install configuration files and an example authority.
|
172
173
|
|
173
|
-
rails generate qa:local
|
174
|
+
rails generate qa:local:files
|
174
175
|
|
175
176
|
This will install a sample states authority file that lists all the states in the U.S. To query it,
|
176
177
|
|
@@ -230,6 +231,44 @@ The second argument is a name of a class that represents your local authority. T
|
|
230
231
|
|
231
232
|
You'll be searching with an instance of `LocalNames`
|
232
233
|
|
234
|
+
### In database tables
|
235
|
+
|
236
|
+
Run the generator to install configuration files and an example authority.
|
237
|
+
|
238
|
+
rails generate qa:local:tables
|
239
|
+
rake db:migrate
|
240
|
+
|
241
|
+
This will create two tables/models Qa::LocalAuthority and Qa::LocalAuthorityEntry. You can then add terms to each:
|
242
|
+
|
243
|
+
language_auth = Qa::LocalAuthority.find_or_create_by(name: 'language')
|
244
|
+
Qa::LocalAuthorityEntry.create(local_authority: language_auth,
|
245
|
+
label: 'French',
|
246
|
+
uri: 'http://id.loc.gov/vocabulary/languages/fre')
|
247
|
+
Qa::LocalAuthorityEntry.create(local_authority: language_auth,
|
248
|
+
label: 'Uighur',
|
249
|
+
uri: 'http://id.loc.gov/vocabulary/languages/uig')
|
250
|
+
|
251
|
+
Unfortunately, Rails doesn't have a mechnism for adding functional indexes to tables, so if you have a lot of rows, you'll want to add an index:
|
252
|
+
|
253
|
+
CREATE INDEX "index_qa_local_authority_entries_on_lower_label" ON
|
254
|
+
"qa_local_authority_entries" (local_authority_id, lower(label))
|
255
|
+
|
256
|
+
Finall you want register your authority in an initializer:
|
257
|
+
|
258
|
+
Qa::Authorities::Local.register_subauthority('languages', 'Qa::Authorities::Local::TableBasedAuthority')
|
259
|
+
|
260
|
+
Then you can search for
|
261
|
+
|
262
|
+
/qa/search/local/languages?q=Fre
|
263
|
+
|
264
|
+
Results are in JSON.
|
265
|
+
|
266
|
+
[{"id":"http://id.loc.gov/vocabulary/languages/fre","label":"French"}]
|
267
|
+
|
268
|
+
The entire list (up to the first 1000 terms) can also be returned using:
|
269
|
+
|
270
|
+
/qa/terms/local/languages/
|
271
|
+
|
233
272
|
|
234
273
|
### Medical Subject Headings (MeSH)
|
235
274
|
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module Qa::Local
|
2
|
+
class FilesGenerator < Rails::Generators::Base
|
3
|
+
source_root File.expand_path('../../templates', __FILE__)
|
4
|
+
|
5
|
+
def copy_local_authority_configs
|
6
|
+
copy_file "config/authorities.yml", "config/authorities.yml"
|
7
|
+
directory "config/authorities"
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rails/generators/active_record/migration'
|
2
|
+
module Qa::Local
|
3
|
+
class TablesGenerator < Rails::Generators::Base
|
4
|
+
source_root File.expand_path('../templates', __FILE__)
|
5
|
+
include ActiveRecord::Generators::Migration
|
6
|
+
|
7
|
+
def migrations
|
8
|
+
generate "model qa/local_authority name:string:uniq"
|
9
|
+
generate "model qa/local_authority_entry local_authority:references label:string uri:string:uniq"
|
10
|
+
message = "Rails doesn't support functional indexes in migrations, so you'll have to add this manually:\n" \
|
11
|
+
"CREATE INDEX \"index_qa_local_authority_entries_on_lower_label\" ON \"qa_local_authority_entries\" (local_authority_id, lower(label))\n" \
|
12
|
+
" OR on Sqlite: \n" \
|
13
|
+
"CREATE INDEX \"index_qa_local_authority_entries_on_lower_label\" ON \"qa_local_authority_entries\" (local_authority_id, label collate nocase)\n"
|
14
|
+
say_status("info", message, :yellow)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
@@ -0,0 +1,6 @@
|
|
1
|
+
class AddIndexToLocalAuthorities < ActiveRecord::Migration
|
2
|
+
# we'd like to be able to run this, but rails quotes the functional index.
|
3
|
+
# add_index :local_authority_entries,
|
4
|
+
# ['local_authority_id', 'lower(label)'],
|
5
|
+
# name: 'index_local_authority_entries_on_lower_label'
|
6
|
+
end
|
@@ -2,9 +2,17 @@ module Qa::Authorities
|
|
2
2
|
class Geonames < Base
|
3
3
|
include WebServiceBase
|
4
4
|
|
5
|
-
class_attribute :username
|
5
|
+
class_attribute :username, :label
|
6
|
+
|
7
|
+
self.label = -> (item) do
|
8
|
+
[item['name'], item['adminName1'], item['countryName']].compact.join(', ')
|
9
|
+
end
|
6
10
|
|
7
11
|
def search q
|
12
|
+
unless username
|
13
|
+
Rails.logger.error "Questioning Authority tried to call geonames, but no username was set"
|
14
|
+
return []
|
15
|
+
end
|
8
16
|
parse_authority_response(json(build_query_url(q)))
|
9
17
|
end
|
10
18
|
|
@@ -36,8 +44,9 @@ module Qa::Authorities
|
|
36
44
|
def parse_authority_response(response)
|
37
45
|
response['geonames'].map do |result|
|
38
46
|
{ 'id' => "http://sws.geonames.org/#{result['geonameId']}",
|
39
|
-
'label' => result
|
47
|
+
'label' => label.call(result) }
|
40
48
|
end
|
41
49
|
end
|
50
|
+
|
42
51
|
end
|
43
52
|
end
|
data/lib/qa/authorities/local.rb
CHANGED
@@ -1,9 +1,36 @@
|
|
1
1
|
module Qa::Authorities
|
2
2
|
module Local
|
3
|
+
extend ActiveSupport::Autoload
|
3
4
|
extend AuthorityWithSubAuthority
|
4
|
-
|
5
|
-
|
5
|
+
autoload :FileBasedAuthority
|
6
|
+
autoload :Registry
|
7
|
+
autoload :TableBasedAuthority
|
6
8
|
|
9
|
+
def self.config
|
10
|
+
@config
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.load_config(file)
|
14
|
+
@config = YAML.load_file(file)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Path to sub-authority files is either the full path to a directory or
|
18
|
+
# the path to a directory relative to the Rails application
|
19
|
+
def self.subauthorities_path
|
20
|
+
if config[:local_path].starts_with?(File::Separator)
|
21
|
+
config[:local_path]
|
22
|
+
else
|
23
|
+
File.join(Rails.root, config[:local_path])
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Local sub-authorities are any YAML files in the subauthorities_path
|
28
|
+
def self.names
|
29
|
+
unless Dir.exists? subauthorities_path
|
30
|
+
raise Qa::ConfigDirectoryNotFound, "There's no directory at #{subauthorities_path}. You must create it in order to use local authorities"
|
31
|
+
end
|
32
|
+
Dir.entries(subauthorities_path).map { |f| File.basename(f, ".yml") if f.match(/yml$/) }.compact
|
33
|
+
end
|
7
34
|
|
8
35
|
def self.subauthority_for(subauthority)
|
9
36
|
validate_subauthority!(subauthority)
|
@@ -18,7 +45,6 @@ module Qa::Authorities
|
|
18
45
|
end
|
19
46
|
end
|
20
47
|
|
21
|
-
|
22
48
|
def self.register_subauthority(subauthority, class_name)
|
23
49
|
registry.add(subauthority, class_name)
|
24
50
|
end
|
@@ -33,54 +59,5 @@ module Qa::Authorities
|
|
33
59
|
reg.add(name, 'Qa::Authorities::Local::FileBasedAuthority')
|
34
60
|
end
|
35
61
|
end
|
36
|
-
|
37
|
-
class Registry
|
38
|
-
def initialize
|
39
|
-
@hash = {}
|
40
|
-
yield self if block_given?
|
41
|
-
end
|
42
|
-
|
43
|
-
def keys
|
44
|
-
@hash.keys
|
45
|
-
end
|
46
|
-
|
47
|
-
def instance_for(key)
|
48
|
-
fetch(key).instance
|
49
|
-
end
|
50
|
-
|
51
|
-
def fetch(key)
|
52
|
-
@hash.fetch(key)
|
53
|
-
end
|
54
|
-
|
55
|
-
def self.logger
|
56
|
-
@logger ||= begin
|
57
|
-
::Rails.logger if defined? Rails and Rails.respond_to? :logger
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def self.logger= logger
|
62
|
-
@logger = logger
|
63
|
-
end
|
64
|
-
|
65
|
-
def add(subauthority, class_name)
|
66
|
-
Registry.logger.debug "Registering Local QA authority: #{subauthority} - #{class_name}"
|
67
|
-
@hash[subauthority] = RegistryEntry.new(subauthority, class_name)
|
68
|
-
end
|
69
|
-
|
70
|
-
|
71
|
-
class RegistryEntry
|
72
|
-
def initialize(subauthority, class_name)
|
73
|
-
@subauthority, @class_name = subauthority, class_name
|
74
|
-
end
|
75
|
-
|
76
|
-
def klass
|
77
|
-
@class_name.constantize
|
78
|
-
end
|
79
|
-
|
80
|
-
def instance
|
81
|
-
klass.new(@subauthority)
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
85
62
|
end
|
86
63
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Qa::Authorities
|
2
|
+
module Local
|
3
|
+
class Registry
|
4
|
+
def initialize
|
5
|
+
@hash = {}
|
6
|
+
yield self if block_given?
|
7
|
+
end
|
8
|
+
|
9
|
+
def keys
|
10
|
+
@hash.keys
|
11
|
+
end
|
12
|
+
|
13
|
+
def instance_for(key)
|
14
|
+
fetch(key).instance
|
15
|
+
end
|
16
|
+
|
17
|
+
def fetch(key)
|
18
|
+
@hash.fetch(key)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.logger
|
22
|
+
@logger ||= begin
|
23
|
+
::Rails.logger if defined? Rails and Rails.respond_to? :logger
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.logger= logger
|
28
|
+
@logger = logger
|
29
|
+
end
|
30
|
+
|
31
|
+
def add(subauthority, class_name)
|
32
|
+
Registry.logger.debug "Registering Local QA authority: #{subauthority} - #{class_name}"
|
33
|
+
@hash[subauthority] = RegistryEntry.new(subauthority, class_name)
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
class RegistryEntry
|
38
|
+
def initialize(subauthority, class_name)
|
39
|
+
@subauthority, @class_name = subauthority, class_name
|
40
|
+
end
|
41
|
+
|
42
|
+
def klass
|
43
|
+
@class_name.constantize
|
44
|
+
end
|
45
|
+
|
46
|
+
def instance
|
47
|
+
klass.new(@subauthority)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Qa::Authorities
|
2
|
+
class Local::TableBasedAuthority < Base
|
3
|
+
def self.check_for_index
|
4
|
+
conn = ActiveRecord::Base.connection
|
5
|
+
if conn.table_exists?('local_authority_entries') && !conn.indexes('local_authority_entries').find { |i| i.name == 'index_local_authority_entries_on_lower_label' }
|
6
|
+
Rails.logger.error "You've installed local authority tables, but you haven't indexed the label. Rails doesn't support functional indexes in migrations, so you'll have to add this manually:\n" \
|
7
|
+
"CREATE INDEX \"index_qa_local_authority_entries_on_lower_label\" ON \"qa_local_authority_entries\" (local_authority_id, lower(label))\n" \
|
8
|
+
" OR on Sqlite: \n" \
|
9
|
+
"CREATE INDEX \"index_qa_local_authority_entries_on_lower_label\" ON \"qa_local_authority_entries\" (local_authority_id, label collate nocase)\n" \
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_reader :subauthority
|
14
|
+
|
15
|
+
def initialize(subauthority)
|
16
|
+
@subauthority = subauthority
|
17
|
+
end
|
18
|
+
|
19
|
+
def search(q)
|
20
|
+
return [] if q.blank?
|
21
|
+
output_set(base_relation.where('lower(label) like ?', "#{q.downcase}%").limit(25))
|
22
|
+
end
|
23
|
+
|
24
|
+
def all
|
25
|
+
output_set(base_relation.limit(1000))
|
26
|
+
end
|
27
|
+
|
28
|
+
def find(uri)
|
29
|
+
record = base_relation.find_by(uri: uri)
|
30
|
+
return unless record
|
31
|
+
output(record)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def base_relation
|
37
|
+
Qa::LocalAuthorityEntry.where(local_authority: local_authority)
|
38
|
+
end
|
39
|
+
|
40
|
+
def output_set(set)
|
41
|
+
set.map { |item| output(item) }
|
42
|
+
end
|
43
|
+
|
44
|
+
def output(item)
|
45
|
+
{ id: item[:uri], label: item[:label] }.with_indifferent_access
|
46
|
+
end
|
47
|
+
|
48
|
+
def local_authority
|
49
|
+
Qa::LocalAuthority.find_by_name(subauthority)
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
data/lib/qa/version.rb
CHANGED
@@ -6,7 +6,7 @@ describe Qa::Authorities::AssignFast do
|
|
6
6
|
describe "#new" do
|
7
7
|
context "without a sub-authority" do
|
8
8
|
it "should raise an exception" do
|
9
|
-
expect {
|
9
|
+
expect { described_class.new }.to raise_error RuntimeError, "Initializing with as sub authority is removed. use Module.subauthority_for(nil) instead"
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
@@ -14,7 +14,7 @@ describe Qa::Authorities::AssignFast do
|
|
14
14
|
describe "#subauthority_for" do
|
15
15
|
context "with an invalid sub-authority" do
|
16
16
|
it "should raise an exception" do
|
17
|
-
expect { Qa::Authorities::AssignFast.subauthority_for("foo") }.to raise_error
|
17
|
+
expect { Qa::Authorities::AssignFast.subauthority_for("foo") }.to raise_error Qa::InvalidSubAuthority
|
18
18
|
end
|
19
19
|
end
|
20
20
|
context "with a valid sub-authority" do
|
@@ -31,7 +31,7 @@ describe Qa::Authorities::Local::FileBasedAuthority do
|
|
31
31
|
end
|
32
32
|
context "YAML file is malformed" do
|
33
33
|
it "should raise an error" do
|
34
|
-
expect { authority_d.all }.to raise_error
|
34
|
+
expect { authority_d.all }.to raise_error Psych::SyntaxError
|
35
35
|
end
|
36
36
|
end
|
37
37
|
end
|
@@ -27,12 +27,35 @@ describe Qa::Authorities::Geonames do
|
|
27
27
|
|
28
28
|
subject { authority.search('whatever') }
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
30
|
+
context "with default label" do
|
31
|
+
it "has id and label keys" do
|
32
|
+
expect(subject.first).to eq("id" => 'http://sws.geonames.org/2088122',
|
33
|
+
"label" => "Port Moresby, National Capital, Papua New Guinea")
|
34
|
+
expect(subject.last).to eq("id" => 'http://sws.geonames.org/377039',
|
35
|
+
"label" => "Port Sudan, Red Sea, Sudan")
|
36
|
+
expect(subject.size).to eq(10)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context "with custom label" do
|
41
|
+
before do
|
42
|
+
@original_label = described_class.label
|
43
|
+
described_class.label = -> (item) { item['name'] }
|
44
|
+
end
|
45
|
+
after do
|
46
|
+
described_class.label = @original_label
|
47
|
+
end
|
48
|
+
it "uses the lambda" do
|
49
|
+
expect(subject.first['label']).to eq("Port Moresby")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context "when username isn't set" do
|
54
|
+
before { described_class.username = nil }
|
55
|
+
it "logs an error" do
|
56
|
+
expect(Rails.logger).to receive(:error).with('Questioning Authority tried to call geonames, but no username was set')
|
57
|
+
expect(subject).to be_empty
|
58
|
+
end
|
36
59
|
end
|
37
60
|
end
|
38
61
|
end
|
@@ -4,20 +4,20 @@ describe Qa::Authorities::Getty do
|
|
4
4
|
|
5
5
|
describe "#new" do
|
6
6
|
it "should raise an exception" do
|
7
|
-
expect { described_class.new }.to raise_error
|
7
|
+
expect { described_class.new }.to raise_error RuntimeError, "Initializing with as sub authority is removed. use Module.subauthority_for(nil) instead"
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
11
|
describe "#subauthority_for" do
|
12
12
|
context "without a sub-authority" do
|
13
13
|
it "should raise an exception" do
|
14
|
-
expect { described_class.subauthority_for }.to raise_error
|
14
|
+
expect { described_class.subauthority_for }.to raise_error ArgumentError
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
18
|
context "with an invalid sub-authority" do
|
19
19
|
it "should raise an exception" do
|
20
|
-
expect { described_class.subauthority_for("foo") }.to raise_error
|
20
|
+
expect { described_class.subauthority_for("foo") }.to raise_error Qa::InvalidSubAuthority
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
@@ -5,7 +5,7 @@ describe Qa::Authorities::Loc do
|
|
5
5
|
describe "#new" do
|
6
6
|
context "without a sub-authority" do
|
7
7
|
it "should raise an exception" do
|
8
|
-
expect {
|
8
|
+
expect { described_class.new }.to raise_error RuntimeError, "Initializing with as sub authority is removed. use Module.subauthority_for(nil) instead"
|
9
9
|
end
|
10
10
|
end
|
11
11
|
end
|
@@ -13,7 +13,7 @@ describe Qa::Authorities::Loc do
|
|
13
13
|
describe "#subauthority_for" do
|
14
14
|
context "with an invalid sub-authority" do
|
15
15
|
it "should raise an exception" do
|
16
|
-
expect { Qa::Authorities::Loc.subauthority_for("foo") }.to raise_error
|
16
|
+
expect { Qa::Authorities::Loc.subauthority_for("foo") }.to raise_error Qa::InvalidSubAuthority
|
17
17
|
end
|
18
18
|
end
|
19
19
|
context "with a valid sub-authority" do
|
@@ -4,17 +4,60 @@ describe Qa::Authorities::Local do
|
|
4
4
|
|
5
5
|
describe "new" do
|
6
6
|
it "should raise an error" do
|
7
|
-
expect { described_class.new }.to raise_error
|
7
|
+
expect { described_class.new }.to raise_error RuntimeError, "Initializing with as sub authority is removed. use Module.subauthority_for(nil) instead"
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
+
describe "#subauthorities_path" do
|
12
|
+
before do
|
13
|
+
@original_path = described_class.config[:local_path]
|
14
|
+
described_class.config[:local_path] = path
|
15
|
+
end
|
16
|
+
after { described_class.config[:local_path] = @original_path }
|
17
|
+
|
18
|
+
context "configured with a full path" do
|
19
|
+
let(:path) { "/full/path" }
|
20
|
+
|
21
|
+
it "returns a full path" do
|
22
|
+
expect(described_class.subauthorities_path).to eq(path)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context "configured with a relative path" do
|
27
|
+
let(:path) { "relative/path" }
|
28
|
+
|
29
|
+
it "returns a path relative to the Rails applicaition" do
|
30
|
+
expect(described_class.subauthorities_path).to eq(File.join(Rails.root, path))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "#names" do
|
36
|
+
it "returns a list of yaml files" do
|
37
|
+
expect(described_class.names).to include("authority_A", "authority_B", "authority_C", "authority_D", "states")
|
38
|
+
end
|
39
|
+
|
40
|
+
context "when the path doesn't exist" do
|
41
|
+
before do
|
42
|
+
@original_path = described_class.config[:local_path]
|
43
|
+
described_class.config[:local_path] = '/foo/bar'
|
44
|
+
end
|
45
|
+
after { described_class.config[:local_path] = @original_path }
|
46
|
+
|
47
|
+
it "raises an error" do
|
48
|
+
expect { described_class.names }.to raise_error Qa::ConfigDirectoryNotFound
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
|
11
54
|
describe ".subauthority_for" do
|
12
55
|
context "without a sub-authority" do
|
13
56
|
it "should raise an error is the sub-authority is not provided" do
|
14
|
-
expect { described_class.subauthority_for }.to raise_error
|
57
|
+
expect { described_class.subauthority_for }.to raise_error ArgumentError
|
15
58
|
end
|
16
59
|
it "should raise an error is the sub-authority does not exist" do
|
17
|
-
expect { described_class.subauthority_for("foo") }.to raise_error
|
60
|
+
expect { described_class.subauthority_for("foo") }.to raise_error Qa::InvalidSubAuthority
|
18
61
|
end
|
19
62
|
end
|
20
63
|
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Qa::Authorities::Local::TableBasedAuthority do
|
4
|
+
|
5
|
+
let(:language) { Qa::Authorities::Local.subauthority_for("language") }
|
6
|
+
let(:subj) { Qa::Authorities::Local.subauthority_for("subject") }
|
7
|
+
|
8
|
+
let(:language_auth) { Qa::LocalAuthority.find_or_create_by(name: 'language') }
|
9
|
+
let(:alternate_auth) { Qa::LocalAuthority.find_or_create_by(name: 'subject') }
|
10
|
+
before do
|
11
|
+
Qa::Authorities::Local.register_subauthority('language', described_class.to_s)
|
12
|
+
Qa::Authorities::Local.register_subauthority('subject', described_class.to_s)
|
13
|
+
Qa::LocalAuthorityEntry.create(local_authority: language_auth, label: 'French', uri: 'http://id.loc.gov/vocabulary/languages/fre')
|
14
|
+
Qa::LocalAuthorityEntry.create(local_authority: language_auth, label: 'Uighur', uri: 'http://id.loc.gov/vocabulary/languages/uig')
|
15
|
+
Qa::LocalAuthorityEntry.create(local_authority: alternate_auth, label: 'French', uri: 'http://example.com/french')
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "#all" do
|
19
|
+
let(:expected) { [ { 'id'=> "A1", 'label' => "Abc Term A1" },
|
20
|
+
{ 'id' => "A2", 'label'=> "Term A2" },
|
21
|
+
{ 'id' => "A3", 'label' => "Abc Term A3" } ] }
|
22
|
+
it "should return all the entries" do
|
23
|
+
expect(language.all).to eq [
|
24
|
+
{"id"=>"http://id.loc.gov/vocabulary/languages/fre", "label"=>"French"},
|
25
|
+
{"id"=>"http://id.loc.gov/vocabulary/languages/uig", "label"=>"Uighur"}]
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#search" do
|
31
|
+
context "with an empty query string" do
|
32
|
+
let(:expected) { [] }
|
33
|
+
it "should return no results" do
|
34
|
+
expect(language.search("")).to eq(expected)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
context "with at least one matching entry" do
|
38
|
+
it "is case insensitive" do
|
39
|
+
expect(language.search("fRe")).to eq [{"id"=>"http://id.loc.gov/vocabulary/languages/fre", "label"=>"French"}]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context "with no matching entries" do
|
44
|
+
it "returns an empty array" do
|
45
|
+
expect(language.search("def")).to be_empty
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "#find" do
|
51
|
+
context "term exists" do
|
52
|
+
it "should return the full term record" do
|
53
|
+
record = language.find('http://id.loc.gov/vocabulary/languages/fre')
|
54
|
+
expect(record).to be_a HashWithIndifferentAccess
|
55
|
+
expect(record).to eq('id' => "http://id.loc.gov/vocabulary/languages/fre",
|
56
|
+
'label' => "French")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
context "term does not exist" do
|
60
|
+
let(:id) { "NonID" }
|
61
|
+
let(:expected) { {} }
|
62
|
+
it "should return an empty hash" do
|
63
|
+
expect(language.find('http://id.loc.gov/vocabulary/languages/eng')).to be_nil
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: qa
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stephen Anderson
|
@@ -15,7 +15,7 @@ authors:
|
|
15
15
|
autorequire:
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
|
-
date: 2016-
|
18
|
+
date: 2016-07-07 00:00:00.000000000 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: rails
|
@@ -208,7 +208,9 @@ files:
|
|
208
208
|
- lib/generators/qa/install/install_generator.rb
|
209
209
|
- lib/generators/qa/install/templates/config/oclcts-authorities.yml
|
210
210
|
- lib/generators/qa/local/USAGE
|
211
|
-
- lib/generators/qa/local/
|
211
|
+
- lib/generators/qa/local/files/files_generator.rb
|
212
|
+
- lib/generators/qa/local/tables/tables_generator.rb
|
213
|
+
- lib/generators/qa/local/tables/templates/add_index_to_local_authorities.rb
|
212
214
|
- lib/generators/qa/local/templates/config/authorities.yml
|
213
215
|
- lib/generators/qa/local/templates/config/authorities/states.yml
|
214
216
|
- lib/qa.rb
|
@@ -228,7 +230,8 @@ files:
|
|
228
230
|
- lib/qa/authorities/loc_subauthority.rb
|
229
231
|
- lib/qa/authorities/local.rb
|
230
232
|
- lib/qa/authorities/local/file_based_authority.rb
|
231
|
-
- lib/qa/authorities/
|
233
|
+
- lib/qa/authorities/local/registry.rb
|
234
|
+
- lib/qa/authorities/local/table_based_authority.rb
|
232
235
|
- lib/qa/authorities/mesh.rb
|
233
236
|
- lib/qa/authorities/mesh_tools.rb
|
234
237
|
- lib/qa/authorities/mesh_tools/mesh_data_parser.rb
|
@@ -278,9 +281,9 @@ files:
|
|
278
281
|
- spec/lib/authorities/local_spec.rb
|
279
282
|
- spec/lib/authorities/mesh_spec.rb
|
280
283
|
- spec/lib/authorities/oclcts_spec.rb
|
284
|
+
- spec/lib/authorities/table_based_authority_spec.rb
|
281
285
|
- spec/lib/authorities/tgnlang_spec.rb
|
282
286
|
- spec/lib/authorities_loc_subauthorities.rb
|
283
|
-
- spec/lib/authorities_local_subauthorities_spec.rb
|
284
287
|
- spec/lib/mesh_data_parser_spec.rb
|
285
288
|
- spec/lib/tasks/mesh.rake_spec.rb
|
286
289
|
- spec/models/subject_mesh_term_spec.rb
|
@@ -348,9 +351,9 @@ test_files:
|
|
348
351
|
- spec/lib/authorities/local_spec.rb
|
349
352
|
- spec/lib/authorities/mesh_spec.rb
|
350
353
|
- spec/lib/authorities/oclcts_spec.rb
|
354
|
+
- spec/lib/authorities/table_based_authority_spec.rb
|
351
355
|
- spec/lib/authorities/tgnlang_spec.rb
|
352
356
|
- spec/lib/authorities_loc_subauthorities.rb
|
353
|
-
- spec/lib/authorities_local_subauthorities_spec.rb
|
354
357
|
- spec/lib/mesh_data_parser_spec.rb
|
355
358
|
- spec/lib/tasks/mesh.rake_spec.rb
|
356
359
|
- spec/models/subject_mesh_term_spec.rb
|
@@ -1,21 +0,0 @@
|
|
1
|
-
module Qa::Authorities::LocalSubauthority
|
2
|
-
|
3
|
-
# Path to sub-authority files is either the full path to a directory or
|
4
|
-
# the path to a directory relative to the Rails application
|
5
|
-
def subauthorities_path
|
6
|
-
if AUTHORITIES_CONFIG[:local_path].starts_with?(File::Separator)
|
7
|
-
AUTHORITIES_CONFIG[:local_path]
|
8
|
-
else
|
9
|
-
File.join(Rails.root, AUTHORITIES_CONFIG[:local_path])
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
# Local sub-authorities are any YAML files in the subauthorities_path
|
14
|
-
def names
|
15
|
-
unless Dir.exists? subauthorities_path
|
16
|
-
raise Qa::ConfigDirectoryNotFound, "There's no directory at #{subauthorities_path}. You must create it in order to use local authorities"
|
17
|
-
end
|
18
|
-
Dir.entries(subauthorities_path).map { |f| File.basename(f, ".yml") if f.match(/yml$/) }.compact
|
19
|
-
end
|
20
|
-
|
21
|
-
end
|
@@ -1,51 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Qa::Authorities::LocalSubauthority do
|
4
|
-
|
5
|
-
before do
|
6
|
-
class TestClass
|
7
|
-
include Qa::Authorities::LocalSubauthority
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
after { Object.send(:remove_const, :TestClass) }
|
12
|
-
|
13
|
-
let(:test) { TestClass.new }
|
14
|
-
|
15
|
-
before { @original_path = AUTHORITIES_CONFIG[:local_path] }
|
16
|
-
after { AUTHORITIES_CONFIG[:local_path] = @original_path }
|
17
|
-
|
18
|
-
describe "#subauthorities_path" do
|
19
|
-
before { AUTHORITIES_CONFIG[:local_path] = path }
|
20
|
-
context "configured with a full path" do
|
21
|
-
let(:path) { "/full/path" }
|
22
|
-
|
23
|
-
it "returns a full path" do
|
24
|
-
expect(test.subauthorities_path).to eq(path)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
context "configured with a relative path" do
|
29
|
-
let(:path) { "relative/path" }
|
30
|
-
|
31
|
-
it "returns a path relative to the Rails applicaition" do
|
32
|
-
expect(test.subauthorities_path).to eq(File.join(Rails.root, path))
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
describe "#names" do
|
38
|
-
it "returns a list of yaml files" do
|
39
|
-
expect(test.names).to include("authority_A", "authority_B", "authority_C", "authority_D", "states")
|
40
|
-
end
|
41
|
-
|
42
|
-
context "when the path doesn't exist" do
|
43
|
-
before { AUTHORITIES_CONFIG[:local_path] = '/foo/bar' }
|
44
|
-
|
45
|
-
it "raises an error" do
|
46
|
-
expect { test.names }.to raise_error Qa::ConfigDirectoryNotFound
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
end
|