qa 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +37 -0
  3. data/app/controllers/qa/terms_controller.rb +1 -1
  4. data/lib/qa/authorities.rb +2 -0
  5. data/lib/qa/authorities/assign_fast.rb +17 -0
  6. data/lib/qa/authorities/assign_fast/generic_authority.rb +61 -0
  7. data/lib/qa/authorities/assign_fast_subauthority.rb +31 -0
  8. data/lib/qa/authorities/getty.rb +12 -3
  9. data/lib/qa/authorities/getty/aat.rb +3 -2
  10. data/lib/qa/authorities/getty/tgn.rb +80 -0
  11. data/lib/qa/authorities/getty/ulan.rb +71 -0
  12. data/lib/qa/authorities/web_service_base.rb +6 -4
  13. data/lib/qa/version.rb +1 -1
  14. data/spec/controllers/terms_controller_spec.rb +26 -12
  15. data/spec/fixtures/assign-fast-noheader.json +1 -0
  16. data/spec/fixtures/assign-fast-noresults.json +10 -0
  17. data/spec/fixtures/assign-fast-oneresult.json +16 -0
  18. data/spec/fixtures/assign-fast-topical-result.json +130 -0
  19. data/spec/fixtures/getty-tgn-find-response.json +1469 -0
  20. data/spec/fixtures/getty-ulan-find-response.json +11565 -0
  21. data/spec/fixtures/tgn-response.txt +87 -0
  22. data/spec/fixtures/ulan-response.txt +1854 -0
  23. data/spec/lib/authorities/assign_fast_spec.rb +115 -0
  24. data/spec/lib/authorities/getty/aat_spec.rb +1 -1
  25. data/spec/lib/authorities/getty/tgn_spec.rb +95 -0
  26. data/spec/lib/authorities/getty/ulan_spec.rb +97 -0
  27. data/spec/lib/authorities/loc_spec.rb +1 -1
  28. data/spec/lib/tasks/mesh.rake_spec.rb +1 -1
  29. data/spec/spec_helper.rb +4 -3
  30. data/spec/test_app_templates/lib/generators/test_app_generator.rb +1 -1
  31. metadata +35 -116
  32. data/spec/internal/Gemfile +0 -44
  33. data/spec/internal/Gemfile.lock +0 -180
  34. data/spec/internal/README.rdoc +0 -28
  35. data/spec/internal/Rakefile +0 -6
  36. data/spec/internal/app/assets/javascripts/application.js +0 -16
  37. data/spec/internal/app/assets/stylesheets/application.css +0 -15
  38. data/spec/internal/app/controllers/application_controller.rb +0 -5
  39. data/spec/internal/app/helpers/application_helper.rb +0 -2
  40. data/spec/internal/app/views/layouts/application.html.erb +0 -14
  41. data/spec/internal/bin/bundle +0 -3
  42. data/spec/internal/bin/rails +0 -4
  43. data/spec/internal/bin/rake +0 -4
  44. data/spec/internal/bin/setup +0 -29
  45. data/spec/internal/config.ru +0 -4
  46. data/spec/internal/config/application.rb +0 -26
  47. data/spec/internal/config/authorities.yml +0 -1
  48. data/spec/internal/config/authorities/authority_A.yml +0 -10
  49. data/spec/internal/config/authorities/authority_B.yml +0 -7
  50. data/spec/internal/config/authorities/authority_C.yml +0 -4
  51. data/spec/internal/config/authorities/authority_D.yml +0 -4
  52. data/spec/internal/config/authorities/states.yml +0 -101
  53. data/spec/internal/config/boot.rb +0 -3
  54. data/spec/internal/config/database.yml +0 -25
  55. data/spec/internal/config/environment.rb +0 -5
  56. data/spec/internal/config/environments/development.rb +0 -41
  57. data/spec/internal/config/environments/production.rb +0 -79
  58. data/spec/internal/config/environments/test.rb +0 -42
  59. data/spec/internal/config/initializers/assets.rb +0 -11
  60. data/spec/internal/config/initializers/backtrace_silencers.rb +0 -7
  61. data/spec/internal/config/initializers/cookies_serializer.rb +0 -3
  62. data/spec/internal/config/initializers/filter_parameter_logging.rb +0 -4
  63. data/spec/internal/config/initializers/inflections.rb +0 -16
  64. data/spec/internal/config/initializers/mime_types.rb +0 -4
  65. data/spec/internal/config/initializers/session_store.rb +0 -3
  66. data/spec/internal/config/initializers/wrap_parameters.rb +0 -14
  67. data/spec/internal/config/locales/en.yml +0 -23
  68. data/spec/internal/config/oclcts-authorities.yml +0 -24
  69. data/spec/internal/config/routes.rb +0 -58
  70. data/spec/internal/config/secrets.yml +0 -22
  71. data/spec/internal/db/development.sqlite3 +0 -0
  72. data/spec/internal/db/migrate/20150311214117_create_qa_subject_mesh_terms.qa.rb +0 -12
  73. data/spec/internal/db/migrate/20150311214118_create_qa_mesh_tree.qa.rb +0 -11
  74. data/spec/internal/db/migrate/20150311214119_add_term_lower_to_qa_subject_mesh_terms.qa.rb +0 -8
  75. data/spec/internal/db/schema.rb +0 -34
  76. data/spec/internal/db/seeds.rb +0 -7
  77. data/spec/internal/db/test.sqlite3 +0 -0
  78. data/spec/internal/lib/generators/test_app_generator.rb +0 -29
  79. data/spec/internal/log/development.log +0 -21909
  80. data/spec/internal/public/404.html +0 -67
  81. data/spec/internal/public/422.html +0 -67
  82. data/spec/internal/public/500.html +0 -66
  83. data/spec/internal/public/favicon.ico +0 -0
  84. data/spec/internal/public/robots.txt +0 -5
  85. data/spec/internal/test/test_helper.rb +0 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6edd488c2f33caee0d368664c08a2f4ea70f3b9e
4
- data.tar.gz: 0bc9d51827a5ece5ce2bf71d8b184d232d859c6b
3
+ metadata.gz: 16b9b7d34d5db8f520bb0a0c3330f75b836d0d01
4
+ data.tar.gz: fcea780be638d13a57f4ccd539f3ce90c5fcca48
5
5
  SHA512:
6
- metadata.gz: 592b389388e0fde9fd85996694ecb44a5bd477cbf78c4b10d066f757989a0d4a6d842d3832f8475bb4b77040afec66131db8ed8df52a4ae81de3789d7c7fffb1
7
- data.tar.gz: 406889f087a33c4089b0f72e43e91f4a542e3569c29116f3657155f30a8591e6a8140c8785ec1fc70e9ac061b9dcb43c371a8b526ee15b5543dbe9fbcbe7b4e8
6
+ metadata.gz: 85bdd4ca0d32bb58b07326aad0a19721fc3efc8139a16af66d8ab54f2c132458a4205e185bf0f5f9038f33f6a5a72d6f964bec722f9a711f8a93c370899dd012
7
+ data.tar.gz: 1a7a76fdc4e0c1b8cb843f95d122f9c21785023779bf19b2ea078845c1aed829a8c9b9709f2947e26b5c81c5d5333f225a6a82995a483544cd39a6ed2bf8c4c9
data/README.md CHANGED
@@ -111,6 +111,43 @@ QA then presents this data to you in JSON format:
111
111
  etc...
112
112
  ]
113
113
 
114
+ ### FAST
115
+
116
+ In the same manner, QA provides a wrapper around OCLC's FAST autocomplete
117
+ service. The following subauthorities are available:
118
+
119
+ * all
120
+ * personal
121
+ * corporate
122
+ * event
123
+ * uniform
124
+ * topical
125
+ * geographic
126
+ * form_genre
127
+
128
+ Example qa URL: /qa/search/assign_fast/all?q=periodic+table
129
+
130
+ The result includes both 'label' and 'value' to help users select the correct
131
+ heading, e.g.:
132
+
133
+ [
134
+ {
135
+ "id":"fst01789629",
136
+ "label":"Periodic table",
137
+ "value":"Periodic table"
138
+ },
139
+ {
140
+ "id":"fst01789629",
141
+ "label":"Periodic table (Saunders, N.) USE Periodic table",
142
+ "value":"Periodic table"
143
+ },...
144
+ ]
145
+
146
+ Make sure you handle these correctly in your form.
147
+
148
+ For more details on this OCLC API, see
149
+ http://www.oclc.org/developer/develop/web-services/fast-api/assign-fast.en.html
150
+
114
151
  ### Local Authorities
115
152
 
116
153
  For simple use cases when you have a few terms that don't change very often.
@@ -30,7 +30,7 @@ class Qa::TermsController < ApplicationController
30
30
 
31
31
  def init_authority
32
32
  begin
33
- mod = authority_class.constantize
33
+ mod = authority_class.camelize.constantize
34
34
  rescue NameError => e
35
35
  logger.warn "Unable to initialize authority #{authority_class}"
36
36
  head :not_found
@@ -13,4 +13,6 @@ module Qa::Authorities
13
13
  autoload :Oclcts
14
14
  autoload :Tgnlang
15
15
  autoload :WebServiceBase
16
+ autoload :AssignFast
17
+ autoload :AssignFastSubauthority
16
18
  end
@@ -0,0 +1,17 @@
1
+ module Qa::Authorities
2
+ # Provide authority namespace
3
+ module AssignFast
4
+ extend AuthorityWithSubAuthority
5
+ extend AssignFastSubauthority
6
+
7
+ require 'qa/authorities/assign_fast/generic_authority'
8
+ # Create an authority object for given subauthority
9
+ #
10
+ # @param [String] subauthority to use
11
+ # @return [GenericAuthority]
12
+ def self.subauthority_for(subauthority)
13
+ validate_subauthority!(subauthority)
14
+ GenericAuthority.new(subauthority)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,61 @@
1
+ module Qa::Authorities
2
+ # A wrapper around the FAST api for use with questioning_authority
3
+ # API documentation:
4
+ # http://www.oclc.org/developer/develop/web-services/fast-api/assign-fast.en.html
5
+ class AssignFast::GenericAuthority < Base
6
+ attr_reader :subauthority
7
+ def initialize(subauthority)
8
+ @subauthority = subauthority
9
+ end
10
+
11
+ include WebServiceBase
12
+
13
+ # Search the FAST api
14
+ #
15
+ # @param [String] the query
16
+ # @return json results
17
+ def search q
18
+ url = build_query_url q
19
+ begin
20
+ raw_response = get_json(url)
21
+ rescue JSON::ParserError => error
22
+ Rails.logger.info "Could not parse response as JSON. Request url: #{url}"
23
+ return []
24
+ end
25
+ parse_authority_response(raw_response)
26
+ end
27
+
28
+ # Build a FAST API url
29
+ #
30
+ # @param [String] the query
31
+ # @return [String] the url
32
+ def build_query_url q
33
+ escaped_query = clean_query_string q
34
+ index = AssignFast.index_for_authority(subauthority)
35
+ return_data = "#{index}%2Cidroot%2Cauth%2Ctype"
36
+ num_rows = 20 # max allowed by the API
37
+ url = "http://fast.oclc.org/searchfast/fastsuggest?&query=#{escaped_query}&queryIndex=#{index}&queryReturn=#{return_data}&suggest=autoSubject&rows=#{num_rows}"
38
+ end
39
+
40
+ private
41
+
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
+
49
+ def parse_authority_response(raw_response)
50
+ results = raw_response['response']['docs'].map do |doc|
51
+ index = AssignFast.index_for_authority(subauthority)
52
+ term = doc[index].first
53
+ if doc['type'] == 'alt'
54
+ term += ' USE ' + doc['auth']
55
+ end
56
+ { id: doc['idroot'], label: term, value: doc['auth'] }
57
+ end
58
+ end
59
+
60
+ end
61
+ end
@@ -0,0 +1,31 @@
1
+ # Encapsulate information about assignFAST subauthorities
2
+ module Qa::Authorities::AssignFastSubauthority
3
+
4
+ # Hash of subauthority names used in qa routes => 'index' used by API
5
+ Subauthorities = {
6
+ 'all' => 'suggestall',
7
+ 'personal' => 'suggest00',
8
+ 'corporate' => 'suggest10',
9
+ 'event' => 'suggest11',
10
+ 'uniform' => 'suggest30',
11
+ 'topical' => 'suggest50',
12
+ 'geographic' => 'suggest51',
13
+ 'form_genre' => 'suggest55',
14
+ }
15
+
16
+ # Get a list of subauthorities by name
17
+ #
18
+ # @return [Array<String>]
19
+ def subauthorities
20
+ Subauthorities.keys
21
+ end
22
+
23
+ # Get an API index name from an English name
24
+ #
25
+ # @param [String] English name
26
+ # @return [String] index name
27
+ def index_for_authority authority
28
+ Subauthorities[authority]
29
+ end
30
+
31
+ end
@@ -3,14 +3,23 @@ require 'uri'
3
3
  module Qa::Authorities
4
4
  module Getty
5
5
  require 'qa/authorities/getty/aat'
6
+ require 'qa/authorities/getty/tgn'
7
+ require 'qa/authorities/getty/ulan'
6
8
  extend AuthorityWithSubAuthority
7
9
 
8
10
  def self.subauthorities
9
- [ "aat" ]
11
+ [ "aat" , "tgn", "ulan" ]
10
12
  end
11
13
 
12
- def self.subauthority_class(_)
13
- AAT
14
+ def self.subauthority_class(subauthority)
15
+ case subauthority
16
+ when 'aat'
17
+ AAT
18
+ when 'tgn'
19
+ TGN
20
+ when 'ulan'
21
+ Ulan
22
+ end
14
23
  end
15
24
  end
16
25
  end
@@ -1,6 +1,7 @@
1
1
  module Qa::Authorities
2
2
  class Getty::AAT < Base
3
3
  include WebServiceBase
4
+
4
5
  def search q
5
6
  parse_authority_response(json(build_query_url(q)))
6
7
  end
@@ -23,7 +24,7 @@ module Qa::Authorities
23
24
  skos:inScheme <http://vocab.getty.edu/aat/> ;
24
25
  gvp:prefLabelGVP [skosxl:literalForm ?name].
25
26
  FILTER regex(?name, \"#{search}\", \"i\") .
26
- } LIMIT 10"
27
+ } ORDER BY ?name"
27
28
  end
28
29
 
29
30
  def untaint(q)
@@ -44,7 +45,7 @@ module Qa::Authorities
44
45
 
45
46
  private
46
47
 
47
- # Reformats the data received from the LOC service
48
+ # Reformats the data received from the Getty service
48
49
  def parse_authority_response(response)
49
50
  response['results']['bindings'].map do |result|
50
51
  { 'id' => result['s']['value'], 'label' => result['name']['value'] }
@@ -0,0 +1,80 @@
1
+ module Qa::Authorities
2
+ class Getty::TGN < Base
3
+ include WebServiceBase
4
+
5
+ def search q
6
+ parse_authority_response(json(build_query_url(q)))
7
+ end
8
+
9
+ # get_json is not ideomatic, so we'll make an alias
10
+ def json(*args)
11
+ get_json(*args)
12
+ end
13
+
14
+ def build_query_url q
15
+ query = URI.escape(sparql(untaint(q)))
16
+ # Replace ampersands, otherwise the query will fail
17
+ # Gsub hack to convert the encoded regex in the REPLACE into a form Getty understands
18
+ "http://vocab.getty.edu/sparql.json?query=#{query.gsub('&','%26').gsub(',[%5E,]+,[%5E,]+$','%2C[^%2C]%2B%2C[^%2C]%2B%24')}&_implicit=false&implicit=true&_equivalent=false&_form=%2Fsparql"
19
+ end
20
+
21
+ # Use a regex to exclude the continent and 'world' from the query
22
+ # If only one word is entered only search the name (not the parent string)
23
+ # If more than one word is entered, one word must appear in the name, and all words in either parent or name
24
+ def sparql(q)
25
+ search = untaint(q)
26
+ if search.include?(' ')
27
+ ex = "(("
28
+ search.split(' ').each do | i |
29
+ ex += "regex(CONCAT(?name, ', ', REPLACE(str(?par), \",[^,]+,[^,]+$\", \"\")), \"#{i}\",\"i\" ) && "
30
+ end
31
+ ex = ex[0..ex.length - 4]
32
+ ex += ') && ('
33
+ search.split(' ').each do | i |
34
+ ex += "regex(?name, \"#{i}\",\"i\" ) || "
35
+ end
36
+ ex = ex[0..ex.length - 4]
37
+ ex += ") )"
38
+
39
+ else
40
+ ex = "regex(?name, \"#{search}\", \"i\")"
41
+ end
42
+
43
+ # The full text index matches on fields besides the term, so we filter to ensure the match is in the term.
44
+ sparql = "SELECT DISTINCT ?s ?name ?par {
45
+ ?s a skos:Concept; luc:term \"#{search}\";
46
+ skos:inScheme <http://vocab.getty.edu/tgn/> ;
47
+ gvp:prefLabelGVP [skosxl:literalForm ?name] ;
48
+ gvp:parentString ?par .
49
+ FILTER #{ex} .
50
+ } ORDER BY ?name ASC(?par)"
51
+ end
52
+
53
+ def untaint(q)
54
+ q.gsub(/[^\w\s-]/, '')
55
+ end
56
+
57
+ def find id
58
+ json(find_url(id))
59
+ end
60
+
61
+ def find_url id
62
+ "http://vocab.getty.edu/tgn/#{id}.json"
63
+ end
64
+
65
+ def request_options
66
+ { accept: 'application/sparql-results+json'}
67
+ end
68
+
69
+ private
70
+
71
+ # Reformats the data received from the service
72
+ # Adds the parentString, minus the contintent and 'World' for disambiguation
73
+ def parse_authority_response(response)
74
+ response['results']['bindings'].map do |result|
75
+ { 'id' => result['s']['value'], 'label' => result['name']['value'] + ' (' + result['par']['value'].gsub(/\,[^\,]+\,[^\,]+$/, '') + ')' }
76
+ end
77
+ end
78
+
79
+ end
80
+ end
@@ -0,0 +1,71 @@
1
+ module Qa::Authorities
2
+ class Getty::Ulan < Base
3
+ include WebServiceBase
4
+
5
+ def search q
6
+ parse_authority_response(json(build_query_url(q)))
7
+ end
8
+
9
+ # get_json is not ideomatic, so we'll make an alias
10
+ def json(*args)
11
+ get_json(*args)
12
+ end
13
+
14
+ def build_query_url q
15
+ query = URI.escape(sparql(untaint(q)))
16
+ # Replace ampersands, otherwise the query will fail
17
+ "http://vocab.getty.edu/sparql.json?query=#{URI.escape(sparql(q)).gsub('&','%26')}&_implicit=false&implicit=true&_equivalent=false&_form=%2Fsparql"
18
+ end
19
+
20
+ def sparql(q)
21
+ search = untaint(q)
22
+ # if more than one term is supplied, check both preferred and alt labels
23
+ if search.include?(' ')
24
+ ex = "("
25
+ search.split(' ').each do | i |
26
+ ex += "regex(CONCAT(?name, ' ', ?alt), \"#{i}\",\"i\" ) && "
27
+ end
28
+ ex = ex[0..ex.length - 4]
29
+ ex += ")"
30
+ else
31
+ ex = "regex(?name, \"#{search}\", \"i\")"
32
+ end
33
+ # The full text index matches on fields besides the term, so we filter to ensure the match is in the term.
34
+ sparql = "SELECT DISTINCT ?s ?name ?bio {
35
+ ?s a skos:Concept; luc:term \"#{search}\";
36
+ skos:inScheme <http://vocab.getty.edu/ulan/> ;
37
+ gvp:prefLabelGVP [skosxl:literalForm ?name] ;
38
+ foaf:focus/gvp:biographyPreferred [schema:description ?bio] ;
39
+ skos:altLabel ?alt .
40
+ FILTER #{ex} .
41
+ } ORDER BY ?name"
42
+ end
43
+
44
+ def untaint(q)
45
+ q.gsub(/[^\w\s-]/, '')
46
+ end
47
+
48
+ def find id
49
+ json(find_url(id))
50
+ end
51
+
52
+ def find_url id
53
+ "http://vocab.getty.edu/ulan/#{id}.json"
54
+ end
55
+
56
+ def request_options
57
+ { accept: 'application/sparql-results+json'}
58
+ end
59
+
60
+ private
61
+
62
+ # Reformats the data received from the Getty service
63
+ # Add the bio for disambiguation
64
+ def parse_authority_response(response)
65
+ response['results']['bindings'].map do |result|
66
+ { 'id' => result['s']['value'], 'label' => result['name']['value'] + ' (' + result['bio']['value'] + ')' }
67
+ end
68
+ end
69
+
70
+ end
71
+ end
@@ -1,4 +1,4 @@
1
- require 'rest_client'
1
+ require 'faraday'
2
2
 
3
3
  module Qa::Authorities
4
4
  module WebServiceBase
@@ -6,12 +6,14 @@ module Qa::Authorities
6
6
 
7
7
  # mix-in to retreive and parse JSON content from the web
8
8
  def get_json(url)
9
- r = RestClient.get url, request_options
9
+ r = response(url).body
10
10
  JSON.parse(r)
11
11
  end
12
12
 
13
- def request_options
14
- { accept: :json }
13
+ def response(url)
14
+ Faraday.get(url) do |req|
15
+ req.headers['Accept'] = 'application/json'
16
+ end
15
17
  end
16
18
  end
17
19
  end
data/lib/qa/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Qa
2
- VERSION = "0.5.0"
2
+ VERSION = "0.6.0"
3
3
  end
@@ -49,20 +49,34 @@ describe Qa::TermsController, :type => :controller do
49
49
 
50
50
  describe "#search" do
51
51
 
52
- before :each do
53
- stub_request(:get, "http://id.loc.gov/search/?format=json&q=Berry&q=cs:http://id.loc.gov/authorities/names").
54
- with(:headers => {'Accept'=>'application/json'}).
55
- to_return(:body => webmock_fixture("loc-names-response.txt"), :status => 200)
56
- end
52
+ context "loc" do
53
+ before :each do
54
+ stub_request(:get, "http://id.loc.gov/search/?format=json&q=Berry&q=cs:http://id.loc.gov/authorities/names").
55
+ with(:headers => {'Accept'=>'application/json'}).
56
+ to_return(:body => webmock_fixture("loc-names-response.txt"), :status => 200)
57
+ end
58
+
59
+ it "should return a set of terms for a tgnlang query" do
60
+ get :search, {:q => "Tibetan", :vocab => "tgnlang" }
61
+ expect(response).to be_success
62
+ end
57
63
 
58
- it "should return a set of terms for a tgnlang query" do
59
- get :search, {:q => "Tibetan", :vocab => "tgnlang" }
60
- expect(response).to be_success
64
+ it "should not return 404 if subauthority is valid" do
65
+ get :search, { :q => "Berry", :vocab => "loc", :subauthority => "names" }
66
+ expect(response).to be_success
67
+ end
61
68
  end
62
69
 
63
- it "should not return 404 if subauthority is valid" do
64
- get :search, { :q => "Berry", :vocab => "loc", :subauthority => "names" }
65
- expect(response).to be_success
70
+ context "assign_fast" do
71
+ before do
72
+ stub_request(:get, "http://fast.oclc.org/searchfast/fastsuggest?query=word&queryIndex=suggest50&queryReturn=suggest50,idroot,auth,type&rows=20&suggest=autoSubject").
73
+ with(:headers => {'Accept'=>'application/json'}).
74
+ to_return(:body => webmock_fixture("assign-fast-topical-result.json"), :status => 200, :headers => {})
75
+ end
76
+ it "succeeds if authority class is camelcase" do
77
+ get :search, { :q => "word", :vocab => "assign_fast", :subauthority => "topical" }
78
+ expect(response).to be_success
79
+ end
66
80
  end
67
81
 
68
82
  end
@@ -103,7 +117,7 @@ describe Qa::TermsController, :type => :controller do
103
117
 
104
118
  before do
105
119
  stub_request(:get, "http://id.loc.gov/authorities/subjects/sh85077565.json").
106
- with(:headers => {'Accept'=>'application/json', 'Accept-Encoding'=>'gzip, deflate', 'User-Agent'=>'Ruby'}).
120
+ with(:headers => {'Accept'=>'application/json'}).
107
121
  to_return(:status => 200, :body => webmock_fixture("loc-names-response.txt"), :headers => {})
108
122
  end
109
123