qa 5.13.0 → 5.15.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/app/controllers/qa/linked_data_terms_controller.rb +10 -5
- data/app/controllers/qa/terms_controller.rb +9 -20
- data/config/authorities/assign_fast/oclc_assign_fast.json +6 -0
- data/lib/qa/authorities/assign_fast/generic_authority.rb +16 -1
- data/lib/qa/authorities/base.rb +3 -0
- data/lib/qa/authorities/linked_data/generic_authority.rb +2 -0
- data/lib/qa/authorities/loc/generic_authority.rb +2 -1
- data/lib/qa/authorities/loc_subauthority.rb +18 -0
- data/lib/qa/authority_request_context.rb +49 -0
- data/lib/qa/authority_wrapper.rb +63 -0
- data/lib/qa/configuration.rb +2 -2
- data/lib/qa/linked_data/authority_service.rb +34 -14
- data/lib/qa/version.rb +1 -1
- data/lib/qa.rb +50 -0
- data/spec/controllers/terms_controller_spec.rb +1 -1
- data/spec/lib/authorities/assign_fast_spec.rb +3 -3
- data/spec/lib/authorities/loc_spec.rb +12 -0
- data/spec/test_app_templates/Gemfile.extra +5 -0
- metadata +7 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 11cbb13006d50dd1457c8782b84f49a677717302d43a3978e3629670ac9ec433
|
4
|
+
data.tar.gz: 72c2de2f8114cc9df223ef68eeac9f3ff9046a74c87dd93103a3461d24c2c15e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 30f799610d3d6980f0e33d3b5fcb2364e9c0019c18f8a12f5474dd22a82ccb865f95cc5f4d49da70df2246fda033ab17ea20dd3da554c220b881841d2a64c1bf
|
7
|
+
data.tar.gz: cc3c22f2e7cb940eff5f7f3d398090ae2caaff78840a81eff1ea9e229d1db2c2a17673617e0cd12fd9aef1a6ffa30128accf66cf8eaa1537b0df901e1847ceac
|
@@ -42,7 +42,7 @@ class Qa::LinkedDataTermsController < ::ApplicationController
|
|
42
42
|
# get "/search/linked_data/:vocab(/:subauthority)"
|
43
43
|
# @see Qa::Authorities::LinkedData::SearchQuery#search
|
44
44
|
def search # rubocop:disable Metrics/MethodLength
|
45
|
-
terms = @authority.search(query
|
45
|
+
terms = @authority.search(query)
|
46
46
|
cors_allow_origin_header(response)
|
47
47
|
render json: terms
|
48
48
|
rescue Qa::ServiceUnavailable
|
@@ -65,7 +65,7 @@ class Qa::LinkedDataTermsController < ::ApplicationController
|
|
65
65
|
# get "/show/linked_data/:vocab/:subauthority/:id
|
66
66
|
# @see Qa::Authorities::LinkedData::FindTerm#find
|
67
67
|
def show # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
68
|
-
term = @authority.find(id
|
68
|
+
term = @authority.find(id)
|
69
69
|
cors_allow_origin_header(response)
|
70
70
|
render json: term, content_type: request_header_service.content_type_for_format
|
71
71
|
rescue Qa::TermNotFound
|
@@ -95,7 +95,7 @@ class Qa::LinkedDataTermsController < ::ApplicationController
|
|
95
95
|
# get "/fetch/linked_data/:vocab"
|
96
96
|
# @see Qa::Authorities::LinkedData::FindTerm#find
|
97
97
|
def fetch # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
98
|
-
term = @authority.find(uri
|
98
|
+
term = @authority.find(uri)
|
99
99
|
cors_allow_origin_header(response)
|
100
100
|
render json: term, content_type: request_header_service.content_type_for_format
|
101
101
|
rescue Qa::TermNotFound
|
@@ -157,9 +157,14 @@ class Qa::LinkedDataTermsController < ::ApplicationController
|
|
157
157
|
@request_header_service = request_header_service_class.new(request: request, params: params)
|
158
158
|
end
|
159
159
|
|
160
|
+
# @see Qa::AuthorityWrapper for these methods
|
161
|
+
delegate :search_header, :fetch_header, to: :request_header_service
|
162
|
+
|
160
163
|
def init_authority
|
161
|
-
@authority = Qa
|
162
|
-
|
164
|
+
@authority = Qa.authority_for(vocab: params[:vocab],
|
165
|
+
subauthority: params[:subauthority],
|
166
|
+
context: self)
|
167
|
+
rescue Qa::InvalidAuthorityError, Qa::InvalidLinkedDataAuthority => e
|
163
168
|
msg = e.message
|
164
169
|
logger.warn msg
|
165
170
|
render json: { errors: msg }, status: :bad_request
|
@@ -69,26 +69,15 @@ class Qa::TermsController < ::ApplicationController
|
|
69
69
|
end
|
70
70
|
|
71
71
|
def init_authority # rubocop:disable Metrics/MethodLength
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
@authority = if mod.is_a? Class
|
82
|
-
mod.new
|
83
|
-
else
|
84
|
-
raise Qa::MissingSubAuthority, "No sub-authority provided" if params[:subauthority].blank?
|
85
|
-
mod.subauthority_for(params[:subauthority])
|
86
|
-
end
|
87
|
-
rescue Qa::InvalidSubAuthority, Qa::MissingSubAuthority => e
|
88
|
-
msg = e.message
|
89
|
-
logger.warn msg
|
90
|
-
render json: { errors: msg }, status: :bad_request
|
91
|
-
end
|
72
|
+
@authority = Qa.authority_for(vocab: params[:vocab],
|
73
|
+
subauthority: params[:subauthority],
|
74
|
+
# Included to preserve error message text
|
75
|
+
try_linked_data_config: false,
|
76
|
+
context: self)
|
77
|
+
rescue Qa::InvalidAuthorityError, Qa::InvalidSubAuthority, Qa::MissingSubAuthority => e
|
78
|
+
msg = e.message
|
79
|
+
logger.warn msg
|
80
|
+
render json: { errors: msg }, status: :bad_request
|
92
81
|
end
|
93
82
|
|
94
83
|
def check_query_param
|
@@ -19,6 +19,7 @@ module Qa::Authorities
|
|
19
19
|
Faraday.get(url) do |req|
|
20
20
|
req.options.params_encoder = space_fix_encoder
|
21
21
|
req.headers['Accept'] = 'application/json'
|
22
|
+
req.options.timeout = connection_timeout_in_seconds unless connection_timeout_in_seconds.nil?
|
22
23
|
end
|
23
24
|
end
|
24
25
|
|
@@ -49,11 +50,25 @@ module Qa::Authorities
|
|
49
50
|
|
50
51
|
# sort=usage+desc is not documented by OCLC but seems necessary to get the sort
|
51
52
|
# we formerly got without specifying, that is most useful in our use case.
|
52
|
-
"
|
53
|
+
"#{assign_fast_url}?&query=#{escaped_query}&queryIndex=#{index}&queryReturn=#{return_data}&suggest=autoSubject&rows=#{num_rows}&sort=usage+desc"
|
53
54
|
end
|
54
55
|
|
55
56
|
private
|
56
57
|
|
58
|
+
# See https://github.com/samvera/questioning_authority/wiki/Connecting-to-OCLC-FAST
|
59
|
+
# for more info about config settings for this authority.
|
60
|
+
def assign_fast_config
|
61
|
+
Qa.config.assign_fast_authority_configs
|
62
|
+
end
|
63
|
+
|
64
|
+
def connection_timeout_in_seconds
|
65
|
+
assign_fast_config.dig(:OCLC_ASSIGN_FAST, :search, :connection, :timeout)&.to_i
|
66
|
+
end
|
67
|
+
|
68
|
+
def assign_fast_url
|
69
|
+
assign_fast_config.dig(:OCLC_ASSIGN_FAST, :search, :urls, :fastsuggest) || 'https://fast.oclc.org/searchfast/fastsuggest'
|
70
|
+
end
|
71
|
+
|
57
72
|
# Removes characters from the query string that are not tolerated by the API
|
58
73
|
# See oclc sample code at
|
59
74
|
# http://experimental.worldcat.org/fast/assignfast/js/assignFASTComplete.js
|
data/lib/qa/authorities/base.rb
CHANGED
@@ -35,7 +35,8 @@ module Qa::Authorities
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def find_url(id)
|
38
|
-
|
38
|
+
root_fetch_slug = Loc.root_fetch_slug_for(@subauthority)
|
39
|
+
File.join("https://id.loc.gov/", root_fetch_slug, "/#{@subauthority}/#{id}.json")
|
39
40
|
end
|
40
41
|
|
41
42
|
private
|
@@ -1,4 +1,5 @@
|
|
1
1
|
module Qa::Authorities::LocSubauthority
|
2
|
+
# @todo Rename to reflect that this is a URI encoded url fragement used only for searching.
|
2
3
|
def get_url_for_authority(authority)
|
3
4
|
if authorities.include?(authority) then authority_base_url
|
4
5
|
elsif vocabularies.include?(authority) then vocab_base_url
|
@@ -7,6 +8,23 @@ module Qa::Authorities::LocSubauthority
|
|
7
8
|
end
|
8
9
|
end
|
9
10
|
|
11
|
+
# @note The returned value is the root directory of the URL. The graphicMaterials sub-authority
|
12
|
+
# has a "type" of vocabulary. https://id.loc.gov/vocabulary/graphicMaterials/tgm008083.html
|
13
|
+
# In some cases, this is plural and in others this is singular.
|
14
|
+
#
|
15
|
+
# @param authority [String] the LOC authority that matches one of the types
|
16
|
+
# @return [String]
|
17
|
+
#
|
18
|
+
# @note there is a relationship between the returned value and the encoded URLs returned by
|
19
|
+
# {#get_url_for_authority}.
|
20
|
+
def root_fetch_slug_for(authority)
|
21
|
+
validate_subauthority!(authority)
|
22
|
+
return "authorities" if authorities.include?(authority)
|
23
|
+
return "vocabulary" if vocabularies.include?(authority)
|
24
|
+
return "datatype" if datatypes.include?(authority)
|
25
|
+
return "vocabulary/preservation" if preservation.include?(authority)
|
26
|
+
end
|
27
|
+
|
10
28
|
def authorities
|
11
29
|
[
|
12
30
|
"subjects",
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Qa
|
2
|
+
# @note THIS IS NOT TESTED NOR EXERCISED CODE IT IS PROVIDED AS CONJECTURE. FUTURE CHANGES MIGHT
|
3
|
+
# BUILD AND REFACTOR UPON THIS.
|
4
|
+
#
|
5
|
+
# @api private
|
6
|
+
# @abstract
|
7
|
+
#
|
8
|
+
# This class is responsible for exposing methods that are required by both linked data and
|
9
|
+
# non-linked data authorities. As of v5.10.0, those three methods are: params, search_header,
|
10
|
+
# fetch_header. Those are the methods that are used in {Qa::LinkedData::RequestHeaderService} and
|
11
|
+
# in {Qa::Authorities::Discogs::GenericAuthority}.
|
12
|
+
#
|
13
|
+
# The intention is to provide a class that can behave like a controller object without being that
|
14
|
+
# entire controller object.
|
15
|
+
#
|
16
|
+
# @see Qa::LinkedData::RequestHeaderService
|
17
|
+
# @see Qa::Authorities::Discogs::GenericAuthority
|
18
|
+
class AuthorityRequestContext
|
19
|
+
def self.fallback
|
20
|
+
new
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize(params: {}, headers: {}, **kwargs)
|
24
|
+
@params = params
|
25
|
+
@headers = headers
|
26
|
+
(SEARCH_HEADER_KEYS + FETCH_HEADER_KEYS).uniq.each do |key|
|
27
|
+
send("#{key}=", kwargs[key]) if kwargs.key?(key)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
SEARCH_HEADER_KEYS = %i[request request_id subauthority user_language performance_data context response_header replacements].freeze
|
32
|
+
FETCH_HEADER_KEYS = %i[request request_id subauthority user_language performance_data format response_header replacements].freeze
|
33
|
+
|
34
|
+
attr_accessor :params, :headers
|
35
|
+
attr_accessor(*(SEARCH_HEADER_KEYS + FETCH_HEADER_KEYS).uniq)
|
36
|
+
|
37
|
+
def search_header
|
38
|
+
SEARCH_HEADER_KEYS.each_with_object(headers.deep_dup) do |key, header|
|
39
|
+
header[key] = send(key) if send(key).present?
|
40
|
+
end.compact
|
41
|
+
end
|
42
|
+
|
43
|
+
def fetch_header
|
44
|
+
FETCH_HEADER_KEYS.each_with_object(headers.deep_dup) do |key, header|
|
45
|
+
header[key] = send(key) if send(key).present?
|
46
|
+
end.compact
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Qa
|
2
|
+
# @api public
|
3
|
+
# @since v5.11.0
|
4
|
+
#
|
5
|
+
# The intention of this wrapper is to provide a common interface that both linked and non-linked
|
6
|
+
# data can use. There are implementation differences between the two, but with this wrapper, the
|
7
|
+
# goal is to draw attention to those differences and insulate the end user from those issues.
|
8
|
+
#
|
9
|
+
# One benefit in introducing this class is that when interacting with a questioning authority
|
10
|
+
# implementation you don't need to consider "Hey when I instantiate an authority, is this linked
|
11
|
+
# data or not?" And what specifically are the parameter differences. You will need to perhaps
|
12
|
+
# include some additional values in the context if you don't call this from a controller.
|
13
|
+
class AuthorityWrapper
|
14
|
+
require 'qa/authority_request_context.rb'
|
15
|
+
# @param authority [#find, #search]
|
16
|
+
# @param subauthority [#to_s]
|
17
|
+
# @param context [#params, #search_header, #fetch_header]
|
18
|
+
def initialize(authority:, subauthority:, context:)
|
19
|
+
@authority = authority
|
20
|
+
@subauthority = subauthority
|
21
|
+
@context = context
|
22
|
+
configure!
|
23
|
+
end
|
24
|
+
attr_reader :authority, :context, :subauthority
|
25
|
+
|
26
|
+
def search(value)
|
27
|
+
if linked_data?
|
28
|
+
# should respond to search_header
|
29
|
+
authority.search(value, request_header: context.search_header)
|
30
|
+
elsif authority.method(:search).arity == 2
|
31
|
+
# This context should respond to params; see lib/qa/authorities/discogs/generic_authority.rb
|
32
|
+
authority.search(value, context)
|
33
|
+
else
|
34
|
+
authority.search(value)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# context has params
|
39
|
+
def find(value)
|
40
|
+
if linked_data?
|
41
|
+
# should respond to fetch_header
|
42
|
+
authority.find(value, request_header: context.fetch_header)
|
43
|
+
elsif authority.method(:find).arity == 2
|
44
|
+
authority.find(value, context)
|
45
|
+
else
|
46
|
+
authority.find(value)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
alias fetch find
|
50
|
+
|
51
|
+
def method_missing(method_name, *arguments, &block)
|
52
|
+
authority.send(method_name, *arguments, &block)
|
53
|
+
end
|
54
|
+
|
55
|
+
def respond_to_missing?(method_name, include_private = false)
|
56
|
+
authority.respond_to?(method_name, include_private)
|
57
|
+
end
|
58
|
+
|
59
|
+
def configure!
|
60
|
+
@context.subauthority = @subauthority if @context.respond_to?(:subauthority)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/qa/configuration.rb
CHANGED
@@ -28,8 +28,8 @@ module Qa
|
|
28
28
|
token == authorized_reload_token
|
29
29
|
end
|
30
30
|
|
31
|
-
# Hold
|
32
|
-
attr_accessor :linked_data_authority_configs
|
31
|
+
# Hold authority configs
|
32
|
+
attr_accessor :linked_data_authority_configs, :assign_fast_authority_configs
|
33
33
|
|
34
34
|
# For linked data access, specify default language for sorting and selection. The default is only used if a language is not
|
35
35
|
# specified in the authority's configuration file and not passed in as a parameter. (e.g. :en, [:en], or [:en, :fr])
|
@@ -2,25 +2,45 @@
|
|
2
2
|
module Qa
|
3
3
|
module LinkedData
|
4
4
|
class AuthorityService
|
5
|
-
# Load or reload the linked data configuration files
|
6
5
|
def self.load_authorities
|
7
|
-
|
8
|
-
|
6
|
+
load_linked_data_config
|
7
|
+
load_assign_fast_config
|
8
|
+
end
|
9
|
+
|
10
|
+
# Load or reload the linked data configuration files
|
11
|
+
def self.load_linked_data_config
|
12
|
+
ld_auth_cfg = {}
|
13
|
+
# Linked data settings
|
9
14
|
Dir[File.join(Qa::Engine.root, 'config', 'authorities', 'linked_data', '*.json')].each do |fn|
|
10
|
-
|
11
|
-
json = File.read(File.expand_path(fn, __FILE__))
|
12
|
-
cfg = JSON.parse(json).deep_symbolize_keys
|
13
|
-
auth_cfg[auth] = cfg
|
15
|
+
process_config_file(file_path: fn, config_hash: ld_auth_cfg)
|
14
16
|
end
|
15
|
-
|
16
|
-
# load app configured linked data authorities and overrides
|
17
|
+
# Optional local (app) linked data settings overrides
|
17
18
|
Dir[Rails.root.join('config', 'authorities', 'linked_data', '*.json')].each do |fn|
|
18
|
-
|
19
|
-
json = File.read(File.expand_path(fn, __FILE__))
|
20
|
-
cfg = JSON.parse(json).deep_symbolize_keys
|
21
|
-
auth_cfg[auth] = cfg
|
19
|
+
process_config_file(file_path: fn, config_hash: ld_auth_cfg)
|
22
20
|
end
|
23
|
-
Qa.config.linked_data_authority_configs =
|
21
|
+
Qa.config.linked_data_authority_configs = ld_auth_cfg
|
22
|
+
end
|
23
|
+
|
24
|
+
# similar to the above; these settings are for getting (non-linked-data) FAST subject headings from OCLC.
|
25
|
+
def self.load_assign_fast_config
|
26
|
+
assign_fast_auth_cfg = {}
|
27
|
+
# assign_fast settings
|
28
|
+
Dir[File.join(Qa::Engine.root, 'config', 'authorities', 'assign_fast', '*.json')].each do |fn|
|
29
|
+
process_config_file(file_path: fn, config_hash: assign_fast_auth_cfg)
|
30
|
+
end
|
31
|
+
# Optional local (app) assign_fast settings overrides
|
32
|
+
Dir[Rails.root.join('config', 'authorities', 'assign_fast', '*.json')].each do |fn|
|
33
|
+
process_config_file(file_path: fn, config_hash: assign_fast_auth_cfg)
|
34
|
+
end
|
35
|
+
Qa.config.assign_fast_authority_configs = assign_fast_auth_cfg
|
36
|
+
end
|
37
|
+
|
38
|
+
# load settings into a configuration hash:
|
39
|
+
def self.process_config_file(file_path:, config_hash:)
|
40
|
+
file_key = File.basename(file_path, '.json').upcase.to_sym
|
41
|
+
json = File.read(File.expand_path(file_path, __FILE__))
|
42
|
+
cfg = JSON.parse(json).deep_symbolize_keys
|
43
|
+
config_hash[file_key] = cfg
|
24
44
|
end
|
25
45
|
|
26
46
|
# Get the list of names of the loaded authorities
|
data/lib/qa/version.rb
CHANGED
data/lib/qa.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require "qa/engine"
|
2
2
|
require "active_record"
|
3
3
|
require "activerecord-import"
|
4
|
+
require "qa/authority_wrapper"
|
4
5
|
|
5
6
|
module Qa
|
6
7
|
extend ActiveSupport::Autoload
|
@@ -30,6 +31,13 @@ module Qa
|
|
30
31
|
warn "[DEPRECATED] #{in_msg}#{msg} It will be removed in the next major release."
|
31
32
|
end
|
32
33
|
|
34
|
+
# Raised when the authority is not valid
|
35
|
+
class InvalidAuthorityError < RuntimeError
|
36
|
+
def initialize(authority_class)
|
37
|
+
super "Unable to initialize authority #{authority_class}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
33
41
|
# Raised when the configuration directory for local authorities doesn't exist
|
34
42
|
class ConfigDirectoryNotFound < StandardError; end
|
35
43
|
|
@@ -67,4 +75,46 @@ module Qa
|
|
67
75
|
|
68
76
|
# Raised when data is returned but cannot be normalized
|
69
77
|
class DataNormalizationError < StandardError; end
|
78
|
+
|
79
|
+
# @api public
|
80
|
+
# @since 5.11.0
|
81
|
+
#
|
82
|
+
# @param vocab [String]
|
83
|
+
# @param subauthority [String]
|
84
|
+
# @param context [#params, #search_header, #fetch_header]
|
85
|
+
# @param try_linked_data_config [Boolean] when true attempt to check for a linked data authority;
|
86
|
+
# this is included as an option to help preserve error messaging from the 5.10.0 branch.
|
87
|
+
# Unless you want to mirror the error messages of `Qa::TermsController#init_authority` then
|
88
|
+
# use the default value.
|
89
|
+
#
|
90
|
+
# @note :try_linked_data_config is included to preserve error message text; something which is
|
91
|
+
# extensively tested in this gem.
|
92
|
+
#
|
93
|
+
# @return [#search, #find] an authority that will respond to #search and #find; and in some cases
|
94
|
+
# #fetch. This is provided as a means of normalizing how we initialize an authority.
|
95
|
+
# And to provide a means to request an authority both within a controller request cycle as
|
96
|
+
# well as outside of that cycle.
|
97
|
+
def self.authority_for(vocab:, context:, subauthority: nil, try_linked_data_config: true)
|
98
|
+
authority = build_authority_for(vocab: vocab,
|
99
|
+
subauthority: subauthority,
|
100
|
+
try_linked_data_config: try_linked_data_config)
|
101
|
+
AuthorityWrapper.new(authority: authority, subauthority: subauthority, context: context)
|
102
|
+
end
|
103
|
+
|
104
|
+
# @api private
|
105
|
+
def self.build_authority_for(vocab:, subauthority: nil, try_linked_data_config: true)
|
106
|
+
authority_constant_name = "Qa::Authorities::#{vocab.to_s.camelcase}"
|
107
|
+
authority_constant = authority_constant_name.safe_constantize
|
108
|
+
if authority_constant.nil?
|
109
|
+
return Qa::Authorities::LinkedData::GenericAuthority.new(vocab.upcase.to_sym) if try_linked_data_config
|
110
|
+
|
111
|
+
raise InvalidAuthorityError, authority_constant_name
|
112
|
+
end
|
113
|
+
|
114
|
+
return authority_constant.new if authority_constant.is_a?(Class)
|
115
|
+
return authority_constant.subauthority_for(subauthority) if subauthority.present?
|
116
|
+
|
117
|
+
raise Qa::MissingSubAuthority, "No sub-authority provided"
|
118
|
+
end
|
119
|
+
private_class_method :build_authority_for
|
70
120
|
end
|
@@ -199,7 +199,7 @@ describe Qa::TermsController, type: :controller do
|
|
199
199
|
|
200
200
|
context "assign_fast" do
|
201
201
|
before do
|
202
|
-
stub_request(:get, "
|
202
|
+
stub_request(:get, "https://fast.oclc.org/searchfast/fastsuggest?query=word&queryIndex=suggest50&queryReturn=suggest50,idroot,auth,type&rows=20&suggest=autoSubject&sort=usage+desc")
|
203
203
|
.with(headers: { 'Accept' => 'application/json' })
|
204
204
|
.to_return(body: webmock_fixture("assign-fast-topical-result.json"), status: 200, headers: {})
|
205
205
|
end
|
@@ -2,7 +2,7 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Qa::Authorities::AssignFast do
|
4
4
|
let(:query) { "word (ling" }
|
5
|
-
let(:expected_url) { "
|
5
|
+
let(:expected_url) { "https://fast.oclc.org/searchfast/fastsuggest?&query=word%20ling&queryIndex=suggestall&queryReturn=suggestall%2Cidroot%2Cauth%2Ctype&suggest=autoSubject&rows=20&sort=usage+desc" }
|
6
6
|
|
7
7
|
# subauthority infrastructure
|
8
8
|
describe "#new" do
|
@@ -60,7 +60,7 @@ describe Qa::Authorities::AssignFast do
|
|
60
60
|
|
61
61
|
context "when query is blank" do
|
62
62
|
let(:query) { "" }
|
63
|
-
let(:expected_url) { "
|
63
|
+
let(:expected_url) { "https://fast.oclc.org/searchfast/fastsuggest?&query=&queryIndex=suggestall&queryReturn=suggestall%2Cidroot%2Cauth%2Ctype&suggest=autoSubject&rows=20&sort=usage+desc" }
|
64
64
|
|
65
65
|
# server returns results but no results header
|
66
66
|
let :results do
|
@@ -104,7 +104,7 @@ describe Qa::Authorities::AssignFast do
|
|
104
104
|
|
105
105
|
context "with topical results" do
|
106
106
|
let(:query) { "word" }
|
107
|
-
let(:expected_url) { "
|
107
|
+
let(:expected_url) { "https://fast.oclc.org/searchfast/fastsuggest?query=word&queryIndex=suggest50&queryReturn=suggest50,idroot,auth,type&rows=20&suggest=autoSubject&sort=usage+desc" }
|
108
108
|
|
109
109
|
let :results do
|
110
110
|
stub_request(:get, expected_url)
|
@@ -42,6 +42,18 @@ describe Qa::Authorities::Loc do
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
|
45
|
+
describe ".root_fetch_slug_for" do
|
46
|
+
it "raises an error for an invalid subauthority" do
|
47
|
+
expect do
|
48
|
+
described_class.root_fetch_slug_for("no-one-would-ever-have-this-one")
|
49
|
+
end.to raise_error Qa::InvalidSubAuthority
|
50
|
+
end
|
51
|
+
|
52
|
+
it "returns the corresponding type for the given subauthority" do
|
53
|
+
expect(described_class.root_fetch_slug_for("graphicMaterials")).to eq("vocabulary")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
45
57
|
describe "#response" do
|
46
58
|
subject { authority.response(url) }
|
47
59
|
let :authority do
|
@@ -21,4 +21,9 @@ group :development do
|
|
21
21
|
# See https://stackoverflow.com/questions/70500220/rails-7-ruby-3-1-loaderror-cannot-load-such-file-net-smtp
|
22
22
|
gem 'net-smtp', require: false
|
23
23
|
end
|
24
|
+
|
25
|
+
if Gem::Version.new(ENV['RAILS_VERSION']) < Gem::Version.new('7.1')
|
26
|
+
gem 'concurrent-ruby', '1.3.4'
|
27
|
+
end
|
28
|
+
|
24
29
|
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: 5.
|
4
|
+
version: 5.15.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stephen Anderson
|
@@ -16,7 +16,7 @@ authors:
|
|
16
16
|
autorequire:
|
17
17
|
bindir: bin
|
18
18
|
cert_chain: []
|
19
|
-
date:
|
19
|
+
date: 2025-06-02 00:00:00.000000000 Z
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
22
|
name: activerecord-import
|
@@ -117,7 +117,7 @@ dependencies:
|
|
117
117
|
version: '5.0'
|
118
118
|
- - "<"
|
119
119
|
- !ruby/object:Gem::Version
|
120
|
-
version: '8.
|
120
|
+
version: '8.1'
|
121
121
|
type: :runtime
|
122
122
|
prerelease: false
|
123
123
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -127,7 +127,7 @@ dependencies:
|
|
127
127
|
version: '5.0'
|
128
128
|
- - "<"
|
129
129
|
- !ruby/object:Gem::Version
|
130
|
-
version: '8.
|
130
|
+
version: '8.1'
|
131
131
|
- !ruby/object:Gem::Dependency
|
132
132
|
name: rdf
|
133
133
|
requirement: !ruby/object:Gem::Requirement
|
@@ -413,6 +413,7 @@ files:
|
|
413
413
|
- app/services/qa/pagination_service.rb
|
414
414
|
- app/views/layouts/qa/application.html.erb
|
415
415
|
- config/authorities.yml
|
416
|
+
- config/authorities/assign_fast/oclc_assign_fast.json
|
416
417
|
- config/authorities/linked_data/loc.json
|
417
418
|
- config/authorities/linked_data/oclc_fast.json
|
418
419
|
- config/authorities/states.yml
|
@@ -501,6 +502,8 @@ files:
|
|
501
502
|
- lib/qa/authorities/oclcts/generic_oclc_authority.rb
|
502
503
|
- lib/qa/authorities/tgnlang.rb
|
503
504
|
- lib/qa/authorities/web_service_base.rb
|
505
|
+
- lib/qa/authority_request_context.rb
|
506
|
+
- lib/qa/authority_wrapper.rb
|
504
507
|
- lib/qa/configuration.rb
|
505
508
|
- lib/qa/data/TGN_LANGUAGES.xml
|
506
509
|
- lib/qa/engine.rb
|