qa 0.7.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|