qa 0.10.1 → 0.10.2
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/Rakefile +12 -2
- data/app/controllers/qa/terms_controller.rb +14 -16
- data/app/models/qa/mesh_tree.rb +3 -5
- data/app/models/qa/subject_mesh_term.rb +15 -15
- data/config/routes.rb +1 -1
- data/lib/generators/qa/install/install_generator.rb +2 -3
- data/lib/generators/qa/local/tables/mysql/mysql_generator.rb +3 -5
- data/lib/generators/qa/local/tables/tables_generator.rb +4 -6
- data/lib/qa/authorities/assign_fast/generic_authority.rb +16 -19
- data/lib/qa/authorities/assign_fast_subauthority.rb +3 -5
- data/lib/qa/authorities/authority_with_sub_authority.rb +1 -2
- data/lib/qa/authorities/base.rb +2 -3
- data/lib/qa/authorities/geonames.rb +11 -12
- data/lib/qa/authorities/getty.rb +7 -8
- data/lib/qa/authorities/getty/aat.rb +11 -12
- data/lib/qa/authorities/getty/tgn.rb +15 -15
- data/lib/qa/authorities/getty/ulan.rb +15 -16
- data/lib/qa/authorities/loc/generic_authority.rb +32 -33
- data/lib/qa/authorities/loc_subauthority.rb +17 -20
- data/lib/qa/authorities/local.rb +41 -40
- data/lib/qa/authorities/local/file_based_authority.rb +18 -19
- data/lib/qa/authorities/local/mysql_table_based_authority.rb +8 -6
- data/lib/qa/authorities/local/registry.rb +5 -5
- data/lib/qa/authorities/local/table_based_authority.rb +26 -19
- data/lib/qa/authorities/mesh.rb +8 -16
- data/lib/qa/authorities/mesh_tools.rb +5 -5
- data/lib/qa/authorities/mesh_tools/mesh_data_parser.rb +4 -6
- data/lib/qa/authorities/mesh_tools/mesh_importer.rb +11 -13
- data/lib/qa/authorities/oclcts.rb +0 -1
- data/lib/qa/authorities/oclcts/generic_oclc_authority.rb +16 -16
- data/lib/qa/authorities/tgnlang.rb +7 -12
- data/lib/qa/version.rb +1 -1
- data/spec/controllers/terms_controller_spec.rb +44 -54
- data/spec/lib/authorities/assign_fast_spec.rb +25 -27
- data/spec/lib/authorities/file_based_authority_spec.rb +25 -26
- data/spec/lib/authorities/geonames_spec.rb +5 -6
- data/spec/lib/authorities/getty/aat_spec.rb +6 -10
- data/spec/lib/authorities/getty/tgn_spec.rb +6 -10
- data/spec/lib/authorities/getty/ulan_spec.rb +6 -10
- data/spec/lib/authorities/getty_spec.rb +4 -5
- data/spec/lib/authorities/loc_spec.rb +30 -36
- data/spec/lib/authorities/local_spec.rb +5 -7
- data/spec/lib/authorities/mesh_spec.rb +9 -9
- data/spec/lib/authorities/mysql_table_based_authority_spec.rb +13 -5
- data/spec/lib/authorities/oclcts_spec.rb +17 -21
- data/spec/lib/authorities/table_based_authority_spec.rb +21 -12
- data/spec/lib/authorities/tgnlang_spec.rb +4 -6
- data/spec/lib/authorities_loc_subauthorities.rb +50 -54
- data/spec/lib/mesh_data_parser_spec.rb +73 -79
- data/spec/lib/services/rdf_authority_parser_spec.rb +2 -7
- data/spec/lib/tasks/mesh.rake_spec.rb +16 -12
- data/spec/models/subject_mesh_term_spec.rb +4 -4
- data/spec/routing/route_spec.rb +13 -15
- data/spec/spec_helper.rb +3 -4
- data/spec/test_app_templates/lib/generators/test_app_generator.rb +0 -1
- metadata +45 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e2bdd4569dfb4ab638c33d27795cfbb461f2559d
|
4
|
+
data.tar.gz: 1ac7796c5f9a0dd23e5721a9c3c5f65e579674d2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f0e9691da5a0d9d980ed2cc7192ad705601c646820a4042366440db60061cdaa953a9cd627c74378442dc06816149f2e38a810c2719c1bbbbe8735ced44fa81a
|
7
|
+
data.tar.gz: d8d96b05bc5e2d3b6ddd808e432df99b0c264a941b4dce2c617e2b854e4fc723e0282464084163af4fd612807262531c4fea13fcae3d5432bd62333e248d2b86
|
data/Rakefile
CHANGED
@@ -2,12 +2,22 @@
|
|
2
2
|
require 'bundler/gem_tasks'
|
3
3
|
require 'engine_cart/rake_task'
|
4
4
|
require 'rspec/core/rake_task'
|
5
|
+
require 'rubocop/rake_task'
|
5
6
|
|
6
7
|
RSpec::Core::RakeTask.new(:spec)
|
7
8
|
|
9
|
+
desc 'Run style checker'
|
10
|
+
RuboCop::RakeTask.new(:rubocop) do |task|
|
11
|
+
task.requires << 'rubocop-rspec'
|
12
|
+
task.fail_on_error = true
|
13
|
+
end
|
14
|
+
|
8
15
|
desc "Run continuous integration build"
|
9
|
-
task :
|
16
|
+
task ci: ['engine_cart:generate'] do
|
10
17
|
Rake::Task['spec'].invoke
|
11
18
|
end
|
12
19
|
|
13
|
-
|
20
|
+
desc 'Run continuous integration build'
|
21
|
+
task ci: ['rubocop', 'spec']
|
22
|
+
|
23
|
+
task default: :ci
|
@@ -4,7 +4,6 @@
|
|
4
4
|
# same methods.
|
5
5
|
|
6
6
|
class Qa::TermsController < ApplicationController
|
7
|
-
|
8
7
|
before_action :check_vocab_param, :init_authority
|
9
8
|
before_action :check_query_param, only: :search
|
10
9
|
|
@@ -32,18 +31,18 @@ class Qa::TermsController < ApplicationController
|
|
32
31
|
def init_authority
|
33
32
|
begin
|
34
33
|
mod = authority_class.camelize.constantize
|
35
|
-
rescue NameError
|
34
|
+
rescue NameError
|
36
35
|
logger.warn "Unable to initialize authority #{authority_class}"
|
37
36
|
head :not_found
|
38
37
|
return
|
39
38
|
end
|
40
39
|
begin
|
41
|
-
@authority = if mod.
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
40
|
+
@authority = if mod.is_a? Class
|
41
|
+
mod.new
|
42
|
+
else
|
43
|
+
raise Qa::MissingSubAuthority, "No sub-authority provided" if params[:subauthority].blank?
|
44
|
+
mod.subauthority_for(params[:subauthority])
|
45
|
+
end
|
47
46
|
rescue Qa::InvalidSubAuthority, Qa::MissingSubAuthority => e
|
48
47
|
logger.warn e.message
|
49
48
|
head :not_found
|
@@ -56,13 +55,12 @@ class Qa::TermsController < ApplicationController
|
|
56
55
|
|
57
56
|
private
|
58
57
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
# converts wildcards into URL-encoded characters
|
64
|
-
def url_search
|
65
|
-
params[:q].gsub("*", "%2A")
|
66
|
-
end
|
58
|
+
def authority_class
|
59
|
+
"Qa::Authorities::" + params[:vocab].capitalize
|
60
|
+
end
|
67
61
|
|
62
|
+
# converts wildcards into URL-encoded characters
|
63
|
+
def url_search
|
64
|
+
params[:q].gsub("*", "%2A")
|
65
|
+
end
|
68
66
|
end
|
data/app/models/qa/mesh_tree.rb
CHANGED
@@ -1,10 +1,8 @@
|
|
1
1
|
class Qa::MeshTree < ActiveRecord::Base
|
2
|
-
belongs_to :subject_mesh_term
|
2
|
+
belongs_to :subject_mesh_term, foreign_key: "term_id"
|
3
3
|
|
4
4
|
def self.classify_all_trees
|
5
|
-
MeshTreeStructure.find_each
|
6
|
-
mts.classify_tree!
|
7
|
-
end
|
5
|
+
MeshTreeStructure.find_each(&:classify_tree!)
|
8
6
|
end
|
9
7
|
|
10
8
|
def eval_tree_path
|
@@ -18,7 +16,7 @@ class Qa::MeshTree < ActiveRecord::Base
|
|
18
16
|
|
19
17
|
def classify_tree
|
20
18
|
tree_levels = initial_segements_of(tree_structure)
|
21
|
-
tree_levels.map
|
19
|
+
tree_levels.map(&:lookup_tree_term)
|
22
20
|
end
|
23
21
|
|
24
22
|
def classify_tree!
|
@@ -1,12 +1,12 @@
|
|
1
1
|
class Qa::SubjectMeshTerm < ActiveRecord::Base
|
2
|
-
has_many :mesh_trees, :
|
2
|
+
has_many :mesh_trees, foreign_key: "term_id"
|
3
3
|
|
4
4
|
def self.from_tree_number(tree_id)
|
5
5
|
Qa::SubjectMeshTerm.joins('INNER JOIN qa_mesh_trees ON qa_subject_mesh_terms.term_id = qa_mesh_trees.term_id').where('qa_mesh_trees.tree_number = ?', tree_id)
|
6
6
|
end
|
7
7
|
|
8
8
|
def trees
|
9
|
-
Qa::MeshTree.where(term_id:
|
9
|
+
Qa::MeshTree.where(term_id: term_id).map(&:tree_number)
|
10
10
|
end
|
11
11
|
|
12
12
|
def synonyms
|
@@ -24,22 +24,22 @@ class Qa::SubjectMeshTerm < ActiveRecord::Base
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def parents
|
27
|
-
t =
|
27
|
+
t = trees
|
28
28
|
t.map { |tn| initial_segements_of(tn) }.flatten.uniq.map { |tn| Qa::SubjectMeshTerm.from_tree_number(tn) }
|
29
29
|
end
|
30
30
|
|
31
31
|
private
|
32
|
-
# Return all of the intial segements of our tree number,
|
33
|
-
# from most general to most specific
|
34
|
-
# e.g. 'D03.456.23.789' returns ['D03', 'D03.456', 'D03.456.23', 'D03.456.23.789']
|
35
|
-
def initial_segements_of(s)
|
36
|
-
result = []
|
37
|
-
loop do
|
38
|
-
result << s
|
39
|
-
s = s.rpartition('.').first
|
40
|
-
break if s.empty?
|
41
|
-
end
|
42
|
-
result.reverse
|
43
|
-
end
|
44
32
|
|
33
|
+
# Return all of the intial segements of our tree number,
|
34
|
+
# from most general to most specific
|
35
|
+
# e.g. 'D03.456.23.789' returns ['D03', 'D03.456', 'D03.456.23', 'D03.456.23.789']
|
36
|
+
def initial_segements_of(s)
|
37
|
+
result = []
|
38
|
+
loop do
|
39
|
+
result << s
|
40
|
+
s = s.rpartition('.').first
|
41
|
+
break if s.empty?
|
42
|
+
end
|
43
|
+
result.reverse
|
44
|
+
end
|
45
45
|
end
|
data/config/routes.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Qa::Engine.routes.draw do
|
2
2
|
get "/terms/:vocab(/:subauthority)", controller: :terms, action: :index
|
3
3
|
get "/search/:vocab(/:subauthority)", controller: :terms, action: :search
|
4
|
-
get "/show/:vocab/:id",
|
4
|
+
get "/show/:vocab/:id", controller: :terms, action: :show
|
5
5
|
get "/show/:vocab/:subauthority/:id", controller: :terms, action: :show
|
6
6
|
end
|
@@ -2,13 +2,12 @@ class Qa::InstallGenerator < Rails::Generators::Base
|
|
2
2
|
source_root File.expand_path('../templates', __FILE__)
|
3
3
|
|
4
4
|
def inject_routes
|
5
|
-
insert_into_file "config/routes.rb", :
|
6
|
-
%
|
5
|
+
insert_into_file "config/routes.rb", after: ".draw do" do
|
6
|
+
%(\n mount Qa::Engine => '/qa'\n)
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
10
10
|
def copy_oclcts_configs
|
11
11
|
copy_file "config/oclcts-authorities.yml", "config/oclcts-authorities.yml"
|
12
12
|
end
|
13
|
-
|
14
13
|
end
|
@@ -6,7 +6,6 @@ module Qa::Local
|
|
6
6
|
include ActiveRecord::Generators::Migration
|
7
7
|
|
8
8
|
def migrations
|
9
|
-
|
10
9
|
unless defined?(ActiveRecord::ConnectionAdapters::Mysql2Adapter) && ActiveRecord::Base.connection.instance_of?(ActiveRecord::ConnectionAdapters::Mysql2Adapter)
|
11
10
|
message = "Use the table based generator if you are not using mysql 'rails generate qa:local:tables'"
|
12
11
|
say_status("error", message, :red)
|
@@ -15,9 +14,9 @@ module Qa::Local
|
|
15
14
|
|
16
15
|
generate "model qa/local_authority name:string:uniq"
|
17
16
|
generate "model qa/local_authority_entry local_authority:references label:string uri:string:uniq lower_label:string"
|
18
|
-
migration_file = Dir.entries(File.join(destination_root,'db/migrate/'))
|
19
|
-
|
20
|
-
migration_file = File.join('db/migrate',migration_file)
|
17
|
+
migration_file = Dir.entries(File.join(destination_root, 'db/migrate/'))
|
18
|
+
.reject { |name| !name.include?('create_qa_local_authority_entries') }.first
|
19
|
+
migration_file = File.join('db/migrate', migration_file)
|
21
20
|
gsub_file migration_file,
|
22
21
|
't.references :local_authority, index: true, foreign_key: true',
|
23
22
|
't.integer :local_authority_id, index: true'
|
@@ -40,4 +39,3 @@ module Qa::Local
|
|
40
39
|
end
|
41
40
|
end
|
42
41
|
end
|
43
|
-
|
@@ -5,16 +5,16 @@ module Qa::Local
|
|
5
5
|
include ActiveRecord::Generators::Migration
|
6
6
|
|
7
7
|
def migrations
|
8
|
-
if defined?(ActiveRecord::ConnectionAdapters::Mysql2Adapter) &&
|
8
|
+
if defined?(ActiveRecord::ConnectionAdapters::Mysql2Adapter) && ActiveRecord::Base.connection.instance_of?(ActiveRecord::ConnectionAdapters::Mysql2Adapter)
|
9
9
|
message = "Use the mysql table based generator if you are using mysql 'rails generate qa:local:tables:mysql'"
|
10
10
|
say_status("error", message, :red)
|
11
11
|
return 0
|
12
12
|
end
|
13
13
|
generate "model qa/local_authority name:string:uniq"
|
14
14
|
generate "model qa/local_authority_entry local_authority:references label:string uri:string:uniq"
|
15
|
-
migration_file = Dir.entries(File.join(destination_root,'db/migrate/'))
|
16
|
-
|
17
|
-
migration_file = File.join('db/migrate',migration_file)
|
15
|
+
migration_file = Dir.entries(File.join(destination_root, 'db/migrate/'))
|
16
|
+
.reject { |name| !name.include?('create_qa_local_authority_entries') }.first
|
17
|
+
migration_file = File.join('db/migrate', migration_file)
|
18
18
|
gsub_file migration_file,
|
19
19
|
't.references :local_authority, index: true, foreign_key: true',
|
20
20
|
't.references :local_authority, foreign_key: { to_table: :qa_local_authorities }, index: true'
|
@@ -25,7 +25,5 @@ module Qa::Local
|
|
25
25
|
"CREATE INDEX \"index_qa_local_authority_entries_on_lower_label\" ON \"qa_local_authority_entries\" (local_authority_id, label collate nocase)\n"
|
26
26
|
say_status("info", message, :yellow)
|
27
27
|
end
|
28
|
-
|
29
28
|
end
|
30
29
|
end
|
31
|
-
|
@@ -14,11 +14,11 @@ module Qa::Authorities
|
|
14
14
|
#
|
15
15
|
# @param [String] the query
|
16
16
|
# @return json results
|
17
|
-
def search
|
17
|
+
def search(q)
|
18
18
|
url = build_query_url q
|
19
19
|
begin
|
20
20
|
raw_response = get_json(url)
|
21
|
-
rescue JSON::ParserError
|
21
|
+
rescue JSON::ParserError
|
22
22
|
Rails.logger.info "Could not parse response as JSON. Request url: #{url}"
|
23
23
|
return []
|
24
24
|
end
|
@@ -29,33 +29,30 @@ module Qa::Authorities
|
|
29
29
|
#
|
30
30
|
# @param [String] the query
|
31
31
|
# @return [String] the url
|
32
|
-
def build_query_url
|
32
|
+
def build_query_url(q)
|
33
33
|
escaped_query = clean_query_string q
|
34
34
|
index = AssignFast.index_for_authority(subauthority)
|
35
35
|
return_data = "#{index}%2Cidroot%2Cauth%2Ctype"
|
36
36
|
num_rows = 20 # max allowed by the API
|
37
|
-
|
37
|
+
"http://fast.oclc.org/searchfast/fastsuggest?&query=#{escaped_query}&queryIndex=#{index}&queryReturn=#{return_data}&suggest=autoSubject&rows=#{num_rows}"
|
38
38
|
end
|
39
39
|
|
40
40
|
private
|
41
41
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
42
|
+
# Removes characters from the query string that are not tolerated by the API
|
43
|
+
# See oclc sample code at
|
44
|
+
# http://experimental.worldcat.org/fast/assignfast/js/assignFASTComplete.js
|
45
|
+
def clean_query_string(q)
|
46
|
+
URI.escape(q.gsub(/-|\(|\)|:/, ""))
|
47
|
+
end
|
48
48
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
49
|
+
def parse_authority_response(raw_response)
|
50
|
+
raw_response['response']['docs'].map do |doc|
|
51
|
+
index = AssignFast.index_for_authority(subauthority)
|
52
|
+
term = doc[index].first
|
53
|
+
term += ' USE ' + doc['auth'] if doc['type'] == 'alt'
|
54
|
+
{ id: doc['idroot'], label: term, value: doc['auth'] }
|
55
55
|
end
|
56
|
-
{ id: doc['idroot'], label: term, value: doc['auth'] }
|
57
56
|
end
|
58
|
-
end
|
59
|
-
|
60
57
|
end
|
61
58
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# Encapsulate information about assignFAST subauthorities
|
2
2
|
module Qa::Authorities::AssignFastSubauthority
|
3
|
-
|
4
3
|
# Hash of subauthority names used in qa routes => 'index' used by API
|
5
4
|
Subauthorities = {
|
6
5
|
'all' => 'suggestall',
|
@@ -10,8 +9,8 @@ module Qa::Authorities::AssignFastSubauthority
|
|
10
9
|
'uniform' => 'suggest30',
|
11
10
|
'topical' => 'suggest50',
|
12
11
|
'geographic' => 'suggest51',
|
13
|
-
'form_genre' => 'suggest55'
|
14
|
-
}
|
12
|
+
'form_genre' => 'suggest55'
|
13
|
+
}.freeze
|
15
14
|
|
16
15
|
# Get a list of subauthorities by name
|
17
16
|
#
|
@@ -24,8 +23,7 @@ module Qa::Authorities::AssignFastSubauthority
|
|
24
23
|
#
|
25
24
|
# @param [String] English name
|
26
25
|
# @return [String] index name
|
27
|
-
def index_for_authority
|
26
|
+
def index_for_authority(authority)
|
28
27
|
Subauthorities[authority]
|
29
28
|
end
|
30
|
-
|
31
29
|
end
|
data/lib/qa/authorities/base.rb
CHANGED
@@ -15,13 +15,12 @@ module Qa::Authorities
|
|
15
15
|
# If the subclassed authority does have this feature
|
16
16
|
# then you will overide the #find method in the subclassed authority.
|
17
17
|
# TODO: need to set some kind of error here
|
18
|
-
def find
|
18
|
+
def find(id)
|
19
19
|
end
|
20
20
|
|
21
|
-
def full_record
|
21
|
+
def full_record(id, _subauthority = nil)
|
22
22
|
Deprecation.warn(".full_record is deprecated. Use .find instead")
|
23
23
|
find(id)
|
24
24
|
end
|
25
|
-
|
26
25
|
end
|
27
26
|
end
|
@@ -4,11 +4,11 @@ module Qa::Authorities
|
|
4
4
|
|
5
5
|
class_attribute :username, :label
|
6
6
|
|
7
|
-
self.label =
|
7
|
+
self.label = lambda do |item|
|
8
8
|
[item['name'], item['adminName1'], item['countryName']].compact.join(', ')
|
9
9
|
end
|
10
10
|
|
11
|
-
def search
|
11
|
+
def search(q)
|
12
12
|
unless username
|
13
13
|
Rails.logger.error "Questioning Authority tried to call geonames, but no username was set"
|
14
14
|
return []
|
@@ -21,7 +21,7 @@ module Qa::Authorities
|
|
21
21
|
get_json(*args)
|
22
22
|
end
|
23
23
|
|
24
|
-
def build_query_url
|
24
|
+
def build_query_url(q)
|
25
25
|
query = URI.escape(untaint(q))
|
26
26
|
"http://api.geonames.org/searchJSON?q=#{query}&username=#{username}&maxRows=10"
|
27
27
|
end
|
@@ -30,23 +30,22 @@ module Qa::Authorities
|
|
30
30
|
q.gsub(/[^\w\s-]/, '')
|
31
31
|
end
|
32
32
|
|
33
|
-
def find
|
33
|
+
def find(id)
|
34
34
|
json(find_url(id))
|
35
35
|
end
|
36
36
|
|
37
|
-
def find_url
|
37
|
+
def find_url(id)
|
38
38
|
"http://www.geonames.org/getJSON?geonameId=#{id}&username=#{username}"
|
39
39
|
end
|
40
40
|
|
41
41
|
private
|
42
42
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
43
|
+
# Reformats the data received from the service
|
44
|
+
def parse_authority_response(response)
|
45
|
+
response['geonames'].map do |result|
|
46
|
+
{ 'id' => "http://sws.geonames.org/#{result['geonameId']}",
|
47
|
+
'label' => label.call(result) }
|
48
|
+
end
|
48
49
|
end
|
49
|
-
end
|
50
|
-
|
51
50
|
end
|
52
51
|
end
|
data/lib/qa/authorities/getty.rb
CHANGED
@@ -8,19 +8,18 @@ module Qa::Authorities
|
|
8
8
|
extend AuthorityWithSubAuthority
|
9
9
|
|
10
10
|
def self.subauthorities
|
11
|
-
[
|
11
|
+
["aat", "tgn", "ulan"]
|
12
12
|
end
|
13
13
|
|
14
14
|
def self.subauthority_class(subauthority)
|
15
15
|
case subauthority
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
16
|
+
when 'aat'
|
17
|
+
AAT
|
18
|
+
when 'tgn'
|
19
|
+
TGN
|
20
|
+
when 'ulan'
|
21
|
+
Ulan
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
25
25
|
end
|
26
|
-
|