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