qa 2.0.0 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +54 -6
  3. data/app/controllers/qa/application_controller.rb +24 -0
  4. data/app/controllers/qa/linked_data_terms_controller.rb +116 -51
  5. data/app/controllers/qa/terms_controller.rb +7 -2
  6. data/app/models/qa/mesh_tree.rb +5 -9
  7. data/app/models/qa/subject_mesh_term.rb +2 -7
  8. data/config/authorities/linked_data/agrovoc.json +8 -1
  9. data/config/initializers/linked_data_authorities.rb +1 -17
  10. data/config/routes.rb +11 -0
  11. data/lib/generators/qa/apidoc/USAGE +11 -0
  12. data/lib/generators/qa/apidoc/apidoc_generator.rb +22 -0
  13. data/lib/generators/qa/apidoc/templates/public/qa/apidoc/apidoc.json +1322 -0
  14. data/lib/generators/qa/apidoc/templates/public/qa/apidoc/favicon-16x16.png +0 -0
  15. data/lib/generators/qa/apidoc/templates/public/qa/apidoc/favicon-32x32.png +0 -0
  16. data/lib/generators/qa/apidoc/templates/public/qa/apidoc/index.html +61 -0
  17. data/lib/generators/qa/apidoc/templates/public/qa/apidoc/oauth2-redirect.html +67 -0
  18. data/lib/generators/qa/apidoc/templates/public/qa/apidoc/swagger-ui-bundle.js +93 -0
  19. data/lib/generators/qa/apidoc/templates/public/qa/apidoc/swagger-ui-bundle.js.map +1 -0
  20. data/lib/generators/qa/apidoc/templates/public/qa/apidoc/swagger-ui-standalone-preset.js +14 -0
  21. data/lib/generators/qa/apidoc/templates/public/qa/apidoc/swagger-ui-standalone-preset.js.map +1 -0
  22. data/lib/generators/qa/apidoc/templates/public/qa/apidoc/swagger-ui.css +3 -0
  23. data/lib/generators/qa/apidoc/templates/public/qa/apidoc/swagger-ui.css.map +1 -0
  24. data/lib/generators/qa/apidoc/templates/public/qa/apidoc/swagger-ui.js +9 -0
  25. data/lib/generators/qa/apidoc/templates/public/qa/apidoc/swagger-ui.js.map +1 -0
  26. data/lib/generators/qa/install/install_generator.rb +11 -0
  27. data/lib/generators/qa/install/templates/config/initializers/qa.rb +13 -0
  28. data/lib/generators/qa/local/tables/mysql/mysql_generator.rb +1 -1
  29. data/lib/generators/qa/local/tables/tables_generator.rb +1 -1
  30. data/lib/qa.rb +16 -0
  31. data/lib/qa/authorities/assign_fast_subauthority.rb +3 -3
  32. data/lib/qa/authorities/getty/aat.rb +13 -6
  33. data/lib/qa/authorities/getty/tgn.rb +11 -22
  34. data/lib/qa/authorities/getty/ulan.rb +13 -16
  35. data/lib/qa/authorities/linked_data.rb +1 -0
  36. data/lib/qa/authorities/linked_data/authority_service.rb +47 -0
  37. data/lib/qa/authorities/linked_data/config.rb +9 -3
  38. data/lib/qa/authorities/linked_data/config/search_config.rb +16 -2
  39. data/lib/qa/authorities/linked_data/config/term_config.rb +17 -3
  40. data/lib/qa/authorities/linked_data/find_term.rb +4 -3
  41. data/lib/qa/authorities/linked_data/generic_authority.rb +8 -1
  42. data/lib/qa/authorities/linked_data/rdf_helper.rb +15 -0
  43. data/lib/qa/authorities/linked_data/search_query.rb +19 -3
  44. data/lib/qa/authorities/loc/generic_authority.rb +2 -2
  45. data/lib/qa/authorities/loc_subauthority.rb +2 -2
  46. data/lib/qa/authorities/local.rb +2 -4
  47. data/lib/qa/authorities/local/file_based_authority.rb +1 -1
  48. data/lib/qa/authorities/local/mysql_table_based_authority.rb +11 -2
  49. data/lib/qa/authorities/local/table_based_authority.rb +2 -1
  50. data/lib/qa/authorities/mesh_tools/mesh_data_parser.rb +1 -1
  51. data/lib/qa/authorities/mesh_tools/mesh_importer.rb +1 -1
  52. data/lib/qa/authorities/oclcts/generic_oclc_authority.rb +1 -3
  53. data/lib/qa/configuration.rb +34 -0
  54. data/lib/qa/version.rb +1 -1
  55. data/lib/tasks/mesh.rake +3 -3
  56. data/spec/controllers/linked_data_terms_controller_spec.rb +247 -18
  57. data/spec/controllers/terms_controller_spec.rb +87 -12
  58. data/spec/fixtures/authorities/linked_data/lod_encoding_config.json +91 -0
  59. data/spec/fixtures/authorities/linked_data/lod_term_id_param_config.json +27 -0
  60. data/spec/fixtures/authorities/linked_data/lod_term_uri_param_config.json +27 -0
  61. data/spec/fixtures/{lexvo_snippet.rdf → lexvo_snippet.rdf.xml} +1 -0
  62. data/spec/lib/authorities/assign_fast_spec.rb +3 -1
  63. data/spec/lib/authorities/file_based_authority_spec.rb +19 -11
  64. data/spec/lib/authorities/geonames_spec.rb +3 -3
  65. data/spec/lib/authorities/getty/aat_spec.rb +14 -8
  66. data/spec/lib/authorities/getty/tgn_spec.rb +8 -15
  67. data/spec/lib/authorities/getty/ulan_spec.rb +8 -6
  68. data/spec/lib/authorities/getty_spec.rb +2 -1
  69. data/spec/lib/authorities/linked_data/authority_service_spec.rb +47 -0
  70. data/spec/lib/authorities/linked_data/generic_authority_spec.rb +56 -14
  71. data/spec/lib/authorities/linked_data/search_config_spec.rb +33 -19
  72. data/spec/lib/authorities/linked_data/search_query_spec.rb +67 -15
  73. data/spec/lib/authorities/linked_data/term_config_spec.rb +34 -20
  74. data/spec/lib/authorities/loc_spec.rb +9 -9
  75. data/spec/lib/authorities/local_spec.rb +7 -8
  76. data/spec/lib/authorities/oclcts_spec.rb +27 -20
  77. data/spec/lib/authorities/table_based_authority_spec.rb +5 -3
  78. data/spec/lib/authorities_loc_subauthorities.rb +2 -2
  79. data/spec/lib/configuration_spec.rb +58 -0
  80. data/spec/lib/mesh_data_parser_spec.rb +2 -0
  81. data/spec/lib/services/rdf_authority_parser_spec.rb +1 -1
  82. data/spec/lib/tasks/mesh.rake_spec.rb +13 -12
  83. data/spec/models/subject_mesh_term_spec.rb +2 -0
  84. data/spec/requests/cors_headers_spec.rb +118 -0
  85. data/spec/spec_helper.rb +2 -2
  86. metadata +167 -137
@@ -11,29 +11,26 @@ module Qa::Authorities
11
11
  "http://vocab.getty.edu/sparql.json?query=#{URI.escape(sparql(q)).gsub('&', '%26')}&_implicit=false&implicit=true&_equivalent=false&_form=%2Fsparql"
12
12
  end
13
13
 
14
- def sparql(q)
14
+ def sparql(q) # rubocop:disable Metrics/MethodLength
15
15
  search = untaint(q)
16
16
  # if more than one term is supplied, check both preferred and alt labels
17
17
  if search.include?(' ')
18
- ex = "("
19
- search.split(' ').each do |i|
20
- ex += "regex(CONCAT(?name, ' ', ?alt), \"#{i}\",\"i\" ) && "
18
+ clauses = search.split(' ').collect do |i|
19
+ %((regex(?name, "#{i}", "i") || regex(?alt, "#{i}", "i")))
21
20
  end
22
- ex = ex[0..ex.length - 4]
23
- ex += ")"
21
+ ex = "(#{clauses.join(' && ')})"
24
22
  else
25
- ex = "regex(?name, \"#{search}\", \"i\")"
23
+ ex = %(regex(?name, "#{search}", "i"))
26
24
  end
27
25
  # The full text index matches on fields besides the term, so we filter to ensure the match is in the term.
28
- sparql = "SELECT DISTINCT ?s ?name ?bio {
29
- ?s a skos:Concept; luc:term \"#{search}\";
30
- skos:inScheme <http://vocab.getty.edu/ulan/> ;
31
- gvp:prefLabelGVP [skosxl:literalForm ?name] ;
32
- foaf:focus/gvp:biographyPreferred [schema:description ?bio] ;
33
- skos:altLabel ?alt .
34
- FILTER #{ex} .
35
- } ORDER BY ?name"
36
- sparql
26
+ %(SELECT DISTINCT ?s ?name ?bio {
27
+ ?s a skos:Concept; luc:term "#{search}";
28
+ skos:inScheme <http://vocab.getty.edu/ulan/> ;
29
+ gvp:prefLabelGVP [skosxl:literalForm ?name] ;
30
+ foaf:focus/gvp:biographyPreferred [schema:description ?bio] ;
31
+ skos:altLabel ?alt .
32
+ FILTER #{ex} .
33
+ } ORDER BY ?name).gsub(/[\s\n]+/, " ")
37
34
  end
38
35
 
39
36
  def untaint(q)
@@ -3,6 +3,7 @@ module Qa::Authorities
3
3
  extend ActiveSupport::Autoload
4
4
  autoload :GenericAuthority
5
5
  autoload :RdfHelper
6
+ autoload :AuthorityService
6
7
  autoload :SearchQuery
7
8
  autoload :FindTerm
8
9
  autoload :Config
@@ -0,0 +1,47 @@
1
+ # This module has the primary QA search method. It also includes methods to process the linked data results and convert
2
+ # them into the expected QA json results format.
3
+ module Qa::Authorities
4
+ module LinkedData
5
+ class AuthorityService
6
+ # Load or reload the linked data configuration files
7
+ def self.load_authorities
8
+ auth_cfg = {}
9
+ # load QA configured linked data authorities
10
+ Dir[File.join(Qa::Engine.root, 'config', 'authorities', 'linked_data', '*.json')].each do |fn|
11
+ auth = File.basename(fn, '.json').upcase.to_sym
12
+ json = File.read(File.expand_path(fn, __FILE__))
13
+ cfg = JSON.parse(json).deep_symbolize_keys
14
+ auth_cfg[auth] = cfg
15
+ end
16
+
17
+ # load app configured linked data authorities and overrides
18
+ Dir[Rails.root.join('config', 'authorities', 'linked_data', '*.json')].each do |fn|
19
+ auth = File.basename(fn, '.json').upcase.to_sym
20
+ json = File.read(File.expand_path(fn, __FILE__))
21
+ cfg = JSON.parse(json).deep_symbolize_keys
22
+ auth_cfg[auth] = cfg
23
+ end
24
+ Qa.config.linked_data_authority_configs = auth_cfg
25
+ end
26
+
27
+ # Get the list of names of the loaded authorities
28
+ # @return [Array<String>] all loaded authority configurations
29
+ def self.authority_configs
30
+ Qa.config.linked_data_authority_configs
31
+ end
32
+
33
+ # Get the configuration for an authority
34
+ # @param [String] name of the authority
35
+ # @return [Array<String>] configuration for the specified authority
36
+ def self.authority_config(authname)
37
+ authority_configs[authname]
38
+ end
39
+
40
+ # Get the list of names of the loaded authorities
41
+ # @return [Array<String>] names of the authority config files that are currently loaded
42
+ def self.authority_names
43
+ authority_configs.keys.sort
44
+ end
45
+ end
46
+ end
47
+ end
@@ -1,6 +1,7 @@
1
1
  require 'qa/authorities/linked_data/config/term_config'.freeze
2
2
  require 'qa/authorities/linked_data/config/search_config'.freeze
3
3
  require 'json'
4
+ require 'erb'
4
5
 
5
6
  # Provide attr_reader methods for linked data authority configurations. Some default configurations are provided for several
6
7
  # linked data authorities and can be found at /config/authorities/linked_data. You can add configurations for new authorities by
@@ -17,6 +18,10 @@ require 'json'
17
18
  module Qa::Authorities
18
19
  module LinkedData
19
20
  class Config
21
+ class << self
22
+ include ERB::Util
23
+ end
24
+
20
25
  attr_reader :authority_name
21
26
  attr_reader :authority_config
22
27
 
@@ -39,7 +44,7 @@ module Qa::Authorities
39
44
  # Return the full configuration for an authority
40
45
  # @return [String] the authority configuration
41
46
  def auth_config
42
- @authority_config ||= LINKED_DATA_AUTHORITIES_CONFIG[@authority_name]
47
+ @authority_config ||= Qa::Authorities::LinkedData::AuthorityService.authority_config(@authority_name)
43
48
  raise Qa::InvalidLinkedDataAuthority, "Unable to initialize linked data authority '#{@authority_name}'" if @authority_config.nil?
44
49
  @authority_config
45
50
  end
@@ -56,7 +61,8 @@ module Qa::Authorities
56
61
  pred_uri
57
62
  end
58
63
 
59
- def self.replace_pattern(url, pattern, value)
64
+ def self.replace_pattern(url, pattern, value, encode = false)
65
+ value = url_encode(value).gsub(".", "%2E") if encode
60
66
  url.gsub("{?#{pattern}}", value)
61
67
  end
62
68
 
@@ -71,7 +77,7 @@ module Qa::Authorities
71
77
  config.each do |param_key, rep_pattern|
72
78
  s_param_key = param_key.to_s
73
79
  value = replacements[param_key] || replacements[s_param_key] || rep_pattern[:default]
74
- url = replace_pattern(url, param_key, value)
80
+ url = replace_pattern(url, param_key, value, rep_pattern[:encode])
75
81
  end
76
82
  url
77
83
  end
@@ -95,12 +95,26 @@ module Qa::Authorities
95
95
  search_config.fetch(:qa_replacement_patterns)
96
96
  end
97
97
 
98
+ # Should the replacement pattern be encoded?
99
+ # @return [Boolean] true, if the pattern should be encoded; otherwise, false
100
+ def qa_replacement_encoded?(pattern_key)
101
+ map_key = qa_replacement_patterns[pattern_key].to_sym
102
+ replacement_encoded? map_key
103
+ end
104
+
98
105
  # Are there replacement parameters configured for search query?
99
106
  # @return [True|False] true if there are replacement parameters configured for search query; otherwise, false
100
107
  def replacements?
101
108
  replacement_count.positive?
102
109
  end
103
110
 
111
+ # Should the replacement parameter be encoded?
112
+ # @return [True|False] true if the replacement parameter should be encoded; otherwise, false
113
+ def replacement_encoded?(map_key)
114
+ return false unless url_mappings[map_key].key? :encode
115
+ url_mappings[map_key][:encode]
116
+ end
117
+
104
118
  # Return the number of possible replacement values to make in the search URL
105
119
  # @return [Integer] the configured number of possible replacements in the search url
106
120
  def replacement_count
@@ -159,8 +173,8 @@ module Qa::Authorities
159
173
  # @return [String] the search encoded url
160
174
  def url_with_replacements(query, sub_auth = nil, search_replacements = {})
161
175
  return nil unless supports_search?
162
- sub_auth = sub_auth.to_sym if sub_auth.is_a? String
163
- url = Config.replace_pattern(url_template, qa_replacement_patterns[:query], query)
176
+ sub_auth = sub_auth.to_sym if sub_auth.present?
177
+ url = Config.replace_pattern(url_template, qa_replacement_patterns[:query], query, qa_replacement_encoded?(:query))
164
178
  url = Config.process_subauthority(url, subauthority_replacement_pattern, subauthorities, sub_auth) if subauthorities?
165
179
  url = Config.apply_replacements(url, replacements, search_replacements) if replacements?
166
180
  url
@@ -112,12 +112,26 @@ module Qa::Authorities
112
112
  Config.config_value(term_config, :qa_replacement_patterns)
113
113
  end
114
114
 
115
+ # Should the replacement pattern be encoded?
116
+ # @return [Boolean] true, if the pattern should be encoded; otherwise, false
117
+ def term_qa_replacement_encoded?(pattern_key)
118
+ map_key = term_qa_replacement_patterns[pattern_key].to_sym
119
+ term_replacement_encoded? map_key
120
+ end
121
+
115
122
  # Are there replacement parameters configured for term fetch?
116
- # @return [True|False] true if there are replacement parameters configured for term fetch; otherwise, false
123
+ # @return [Boolean] true if there are replacement parameters configured for term fetch; otherwise, false
117
124
  def term_replacements?
118
125
  term_replacement_count.positive?
119
126
  end
120
127
 
128
+ # Should the replacement parameter be encoded?
129
+ # @return [Boolean] true if the replacement parameter should be encoded; otherwise, false
130
+ def term_replacement_encoded?(map_key)
131
+ return false unless term_url_mappings[map_key].key? :encode
132
+ term_url_mappings[map_key][:encode]
133
+ end
134
+
121
135
  # Return the number of possible replacement values to make in the term URL
122
136
  # @return [Integer] the configured number of possible replacements in the term url
123
137
  def term_replacement_count
@@ -129,7 +143,7 @@ module Qa::Authorities
129
143
  def term_replacements
130
144
  return @term_replacements unless @term_replacements.nil?
131
145
  @term_replacements = {}
132
- @term_replacements = term_url_mappings.select { |k, _v| !term_qa_replacement_patterns.include?(k) } unless term_config.nil? || term_url_mappings.nil?
146
+ @term_replacements = term_url_mappings.select { |k, _v| !term_qa_replacement_patterns.value?(k.to_s) } unless term_config.nil? || term_url_mappings.nil?
133
147
  @term_replacements
134
148
  end
135
149
 
@@ -176,7 +190,7 @@ module Qa::Authorities
176
190
  def term_url_with_replacements(id, sub_auth = nil, replacements = {})
177
191
  return nil unless supports_term?
178
192
  sub_auth = sub_auth.to_sym if sub_auth.is_a? String
179
- url = Config.replace_pattern(term_url_template, term_qa_replacement_patterns[:term_id], id)
193
+ url = Config.replace_pattern(term_url_template, term_qa_replacement_patterns[:term_id], id, term_qa_replacement_encoded?(:term_id))
180
194
  url = Config.process_subauthority(url, term_subauthority_replacement_pattern, term_subauthorities, sub_auth) if term_subauthorities?
181
195
  url = Config.apply_replacements(url, term_replacements, replacements) if term_replacements?
182
196
  url
@@ -33,13 +33,14 @@ module Qa::Authorities
33
33
  # "http://schema.org/name":["Cornell University","Ithaca (N.Y.). Cornell University"],
34
34
  # "http://www.w3.org/2004/02/skos/core#altLabel":["Ithaca (N.Y.). Cornell University"],
35
35
  # "http://schema.org/sameAs":["http://id.loc.gov/authorities/names/n79021621","https://viaf.org/viaf/126293486"] } }
36
- def find(id, language: nil, replacements: {}, subauth: nil)
36
+ def find(id, language: nil, replacements: {}, subauth: nil, jsonld: false)
37
37
  raise Qa::InvalidLinkedDataAuthority, "Unable to initialize linked data term sub-authority #{subauth}" unless subauth.nil? || term_subauthority?(subauth)
38
38
  language ||= term_config.term_language
39
39
  url = term_config.term_url_with_replacements(id, subauth, replacements)
40
40
  Rails.logger.info "QA Linked Data term url: #{url}"
41
41
  graph = get_linked_data(url)
42
42
  return "{}" unless graph.size.positive?
43
+ return graph.dump(:jsonld, standard_prefixes: true) if jsonld
43
44
  parse_term_authority_response(id, graph, language)
44
45
  end
45
46
 
@@ -76,7 +77,7 @@ module Qa::Authorities
76
77
  preds
77
78
  end
78
79
 
79
- def consolidate_term_results(results)
80
+ def consolidate_term_results(results) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize # TODO: Explore a way to simplify
80
81
  consolidated_results = {}
81
82
  results.each do |statement|
82
83
  stmt_hash = statement.to_h
@@ -123,7 +124,7 @@ module Qa::Authorities
123
124
  json_results.first
124
125
  end
125
126
 
126
- def predicates_with_subject_uri(graph, expected_uri)
127
+ def predicates_with_subject_uri(graph, expected_uri) # rubocop:disable Metrics/MethodLength
127
128
  predicates_hash = {}
128
129
  graph.statements.each do |st|
129
130
  subj = st.subject.to_s
@@ -22,7 +22,13 @@ module Qa::Authorities
22
22
  @auth_config = Qa::Authorities::LinkedData::Config.new(auth_name)
23
23
  end
24
24
 
25
- include WebServiceBase
25
+ def reload_authorities
26
+ @authorities_service.load_authorities
27
+ end
28
+
29
+ def authorities_service
30
+ @authorities_service ||= Qa::Authorities::LinkedData::AuthorityService
31
+ end
26
32
 
27
33
  def search_service
28
34
  @search_service ||= Qa::Authorities::LinkedData::SearchQuery.new(search_config)
@@ -34,6 +40,7 @@ module Qa::Authorities
34
40
 
35
41
  delegate :search, to: :search_service
36
42
  delegate :find, to: :item_service
43
+ delegate :load_authorities, :authority_names, to: :authorities_service
37
44
 
38
45
  private
39
46
 
@@ -57,6 +57,10 @@ module Qa::Authorities
57
57
  msg[a..z]
58
58
  end
59
59
 
60
+ # Filter a graph to the specified languages
61
+ # @param [RDF::Graph] the graph to be filtered.
62
+ # @param [String | Symbol | Array<String|Symbol>] language for filtering graph (e.g. "en" or :en or ["en", "fr"] or [:en, :fr])
63
+ # @returns [RDF::Graph] graph of linked data filtered on the specified languages
60
64
  def filter_language(graph, language)
61
65
  language = normalize_language(language)
62
66
  return graph if language.nil?
@@ -66,6 +70,17 @@ module Qa::Authorities
66
70
  graph
67
71
  end
68
72
 
73
+ # Filter a graph to remove any statement with a blanknode for the subject
74
+ # @param [RDF::Graph] the graph to be filtered.
75
+ # @returns [RDF::Graph] graph of linked data with blanknodes removed
76
+ def filter_out_blanknodes(graph)
77
+ return graph if graph.subjects.blank?
78
+ graph.each do |st|
79
+ graph.delete(st) if st.subject.anonymous?
80
+ end
81
+ graph
82
+ end
83
+
69
84
  def normalize_language(language)
70
85
  language = [language.to_sym] if language.is_a? String
71
86
  language = [language] if language.is_a? Symbol
@@ -37,6 +37,7 @@ module Qa::Authorities
37
37
 
38
38
  def parse_search_authority_response(graph, language)
39
39
  graph = filter_language(graph, language) unless language.nil?
40
+ graph = filter_out_blanknodes(graph)
40
41
  results = extract_preds(graph, preds_for_search)
41
42
  consolidated_results = consolidate_search_results(results)
42
43
  json_results = convert_search_to_json(consolidated_results)
@@ -61,7 +62,7 @@ module Qa::Authorities
61
62
  preds
62
63
  end
63
64
 
64
- def consolidate_search_results(results)
65
+ def consolidate_search_results(results) # rubocop:disable Metrics/MethodLength
65
66
  consolidated_results = {}
66
67
  return consolidated_results if results.nil? || !results.count.positive?
67
68
  results.each do |statement|
@@ -105,11 +106,14 @@ module Qa::Authorities
105
106
  lbl
106
107
  end
107
108
 
108
- def sort_search_results(json_results)
109
+ def sort_search_results(json_results) # rubocop:disable Metrics/MethodLength
109
110
  return json_results unless supports_sort?
110
111
  json_results.sort! do |a, b|
111
112
  cmp = sort_when_missing_sort_predicate(a, b)
112
- next unless cmp.nil?
113
+ next cmp unless cmp.nil?
114
+
115
+ cmp = numeric_sort(a, b)
116
+ next cmp unless cmp.nil?
113
117
 
114
118
  as = a[:sort].collect(&:downcase)
115
119
  bs = b[:sort].collect(&:downcase)
@@ -138,6 +142,18 @@ module Qa::Authorities
138
142
  return 1 if bs.size <= current_list_size # consider shorter b list of values lower then longer a list
139
143
  nil
140
144
  end
145
+
146
+ def numeric_sort(a, b)
147
+ return nil if a[:sort].size > 1
148
+ return nil if b[:sort].size > 1
149
+ return nil unless s_is_i? a[:sort][0]
150
+ return nil unless s_is_i? b[:sort][0]
151
+ Integer(a[:sort][0]) <=> Integer(b[:sort][0])
152
+ end
153
+
154
+ def s_is_i?(s)
155
+ /\A[-+]?\d+\z/ === s # rubocop:disable Style/CaseEquality
156
+ end
141
157
  end
142
158
  end
143
159
  end
@@ -26,7 +26,7 @@ module Qa::Authorities
26
26
  def build_query_url(q)
27
27
  escaped_query = URI.escape(q)
28
28
  authority_fragment = Loc.get_url_for_authority(subauthority) + URI.escape(subauthority)
29
- "http://id.loc.gov/search/?q=#{escaped_query}&q=#{authority_fragment}&format=json"
29
+ "https://id.loc.gov/search/?q=#{escaped_query}&q=#{authority_fragment}&format=json"
30
30
  end
31
31
 
32
32
  def find(id)
@@ -34,7 +34,7 @@ module Qa::Authorities
34
34
  end
35
35
 
36
36
  def find_url(id)
37
- "http://id.loc.gov/authorities/#{@subauthority}/#{id}.json"
37
+ "https://id.loc.gov/authorities/#{@subauthority}/#{id}.json"
38
38
  end
39
39
 
40
40
  private
@@ -18,7 +18,7 @@ module Qa::Authorities::LocSubauthority
18
18
  ]
19
19
  end
20
20
 
21
- def vocabularies
21
+ def vocabularies # rubocop:disable Metrics/MethodLength
22
22
  [
23
23
  "graphicMaterials",
24
24
  "organizations",
@@ -40,7 +40,7 @@ module Qa::Authorities::LocSubauthority
40
40
  ["edtf"]
41
41
  end
42
42
 
43
- def preservation
43
+ def preservation # rubocop:disable Metrics/MethodLength
44
44
  [
45
45
  "contentLocationType",
46
46
  "copyrightStatus",
@@ -20,15 +20,13 @@ module Qa::Authorities
20
20
  if config[:local_path].starts_with?(File::Separator)
21
21
  config[:local_path]
22
22
  else
23
- File.join(Rails.root, config[:local_path])
23
+ Rails.root.join(config[:local_path]).to_s # TODO: Rails.root.join returns class Pathname, which may be ok. Added to_s because of failing regression test.
24
24
  end
25
25
  end
26
26
 
27
27
  # Local sub-authorities are any YAML files in the subauthorities_path
28
28
  def names
29
- unless Dir.exist? 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
29
+ raise Qa::ConfigDirectoryNotFound, "There's no directory at #{subauthorities_path}. You must create it in order to use local authorities" unless Dir.exist? subauthorities_path
32
30
  Dir.entries(subauthorities_path).map { |f| File.basename(f, ".yml") if f =~ /yml$/ }.compact
33
31
  end
34
32
 
@@ -25,7 +25,7 @@ module Qa::Authorities
25
25
  private
26
26
 
27
27
  def terms
28
- subauthority_hash = YAML.load(File.read(subauthority_filename))
28
+ subauthority_hash = YAML.load(File.read(subauthority_filename)) # rubocop:disable Security/YAMLLoad # TODO: Explore how to change this to safe_load. Many tests fail when making this change.
29
29
  terms = subauthority_hash.with_indifferent_access.fetch(:terms, [])
30
30
  normalize_terms(terms)
31
31
  end
@@ -5,8 +5,7 @@ module Qa
5
5
  self.table_index = "index_qa_local_authority_entries_on_lower_label_and_authority"
6
6
 
7
7
  def self.check_for_index
8
- conn = ActiveRecord::Base.connection
9
- if table_or_view_exists? && conn.index_name_exists?(table_name.to_sym, table_index, :default).blank?
8
+ if table_or_view_exists? && index_name_exists? # rubocop:disable Style/GuardClause
10
9
  Rails.logger.error "You've installed mysql local authority tables, but you haven't indexed the lower label. "
11
10
  "Rails doesn't support functional indexes in migrations, so we tried to execute it for you but something went wrong...\n" \
12
11
  "Make sure your table has a lower_label column, which is virtually created, and that the column is indexed." \
@@ -19,6 +18,16 @@ module Qa
19
18
  return [] if q.blank?
20
19
  output_set(base_relation.where('lower_label like ?', "#{q.downcase}%").limit(25))
21
20
  end
21
+
22
+ def self.index_name_exists?
23
+ conn = ActiveRecord::Base.connection
24
+ if ActiveRecord::VERSION::MAJOR >= 5 && ActiveRecord::VERSION::MINOR >= 1
25
+ conn.index_name_exists?(table_name, table_index).blank?
26
+ else
27
+ conn.index_name_exists?(table_name, table_index, :default).blank?
28
+ end
29
+ end
30
+ private_class_method :index_name_exists?
22
31
  end
23
32
  end
24
33
  end