gds-api-adapters 63.6.0 → 67.2.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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +0 -1
  3. data/Rakefile +3 -4
  4. data/lib/gds_api.rb +2 -14
  5. data/lib/gds_api/asset_manager.rb +1 -1
  6. data/lib/gds_api/base.rb +8 -3
  7. data/lib/gds_api/email_alert_api.rb +12 -13
  8. data/lib/gds_api/imminence.rb +3 -3
  9. data/lib/gds_api/json_client.rb +6 -6
  10. data/lib/gds_api/list_response.rb +6 -6
  11. data/lib/gds_api/performance_platform/data_out.rb +21 -21
  12. data/lib/gds_api/publishing_api.rb +2 -2
  13. data/lib/gds_api/publishing_api/special_route_publisher.rb +1 -1
  14. data/lib/gds_api/response.rb +80 -6
  15. data/lib/gds_api/test_helpers/asset_manager.rb +0 -17
  16. data/lib/gds_api/test_helpers/calendars.rb +0 -9
  17. data/lib/gds_api/test_helpers/content_store.rb +0 -9
  18. data/lib/gds_api/test_helpers/email_alert_api.rb +28 -39
  19. data/lib/gds_api/test_helpers/imminence.rb +11 -14
  20. data/lib/gds_api/test_helpers/licence_application.rb +8 -16
  21. data/lib/gds_api/test_helpers/link_checker_api.rb +0 -8
  22. data/lib/gds_api/test_helpers/local_links_manager.rb +0 -13
  23. data/lib/gds_api/test_helpers/mapit.rb +15 -26
  24. data/lib/gds_api/test_helpers/organisations.rb +13 -18
  25. data/lib/gds_api/test_helpers/performance_platform/data_out.rb +34 -34
  26. data/lib/gds_api/test_helpers/publishing_api.rb +32 -51
  27. data/lib/gds_api/test_helpers/support.rb +0 -5
  28. data/lib/gds_api/test_helpers/support_api.rb +16 -20
  29. data/lib/gds_api/test_helpers/worldwide.rb +51 -31
  30. data/lib/gds_api/version.rb +1 -1
  31. metadata +14 -31
  32. data/lib/gds_api/publishing_api_v2.rb +0 -14
  33. data/lib/gds_api/test_helpers/alias_deprecated.rb +0 -13
  34. data/lib/gds_api/test_helpers/publishing_api_v2.rb +0 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c63bd76ee4646694f763c71980fcce76ae359bfd12ad2de8437679eb0f389422
4
- data.tar.gz: 5729acfdc3d52d7fd1c7e053a7740bc09424006088e6ce0631fed2144479e267
3
+ metadata.gz: b9e99044909467134a19c5e0f273908fd94afbe72a40f50a5d81dfd4bf467d28
4
+ data.tar.gz: 0535e351b0d6899aa363f61bcd8c0ab9b3137389b4279bf9ff195250773c087d
5
5
  SHA512:
6
- metadata.gz: 7676cf189a66b0b699c08ae50605a4f481da8b775201876e641167b49d7a6fc33a2139c97f4b7d0801af335e3c32929afc7bb8c6cc562cd2999c889f7603f5c3
7
- data.tar.gz: 2c9f91be586e98a61e91dccf0c8bb66a9db31d1bbac59eccabf13e7fc8689f169126907d15a50ad483cb5605934240438ce5e2fbd97243511718be2278e7c359
6
+ metadata.gz: 796c442ffe778c4377f476db1fdae0d52592c776687aa4d52bc4e3e7f3f3a33fe7cd9e48e40af52e532943fe5b0549cf335ae516d7d4dd149e767f26b7142b7c
7
+ data.tar.gz: 3b37865fca30c9e7ff47bd9e8f64fe4579065b48a325eb59cad29a4722170873049c16373f4708c9601e015269875de3ec88612d2a84d64943337e6494aea9fa
data/README.md CHANGED
@@ -5,7 +5,6 @@ A set of API adapters to work with the GDS APIs.
5
5
  Example usage:
6
6
 
7
7
  ```ruby
8
- require 'gds_api/publishing_api'
9
8
  GdsApi.publishing_api.get_content("f3bbdec2-0e62-4520-a7fd-6ffd5d36e03a")
10
9
  ```
11
10
 
data/Rakefile CHANGED
@@ -1,5 +1,3 @@
1
- # -*- encoding: utf-8 -*-
2
-
3
1
  require "rdoc/task"
4
2
  require "rake/testtask"
5
3
 
@@ -13,7 +11,8 @@ Rake::TestTask.new("test") do |t|
13
11
  t.test_files = FileList["test/**/*_test.rb"]
14
12
  t.warning = false
15
13
  end
16
- task default: :test
14
+
15
+ task default: %i[lint test]
17
16
 
18
17
  require "pact_broker/client/tasks"
19
18
 
@@ -31,5 +30,5 @@ end
31
30
 
32
31
  desc "Run the linter against changed files"
33
32
  task :lint do
34
- sh "bundle exec rubocop --format clang lib test"
33
+ sh "bundle exec rubocop --format clang"
35
34
  end
@@ -1,4 +1,6 @@
1
+ require "addressable"
1
2
  require "plek"
3
+ require "time"
2
4
  require "gds_api/asset_manager"
3
5
  require "gds_api/calendars"
4
6
  require "gds_api/content_store"
@@ -11,7 +13,6 @@ require "gds_api/mapit"
11
13
  require "gds_api/maslow"
12
14
  require "gds_api/organisations"
13
15
  require "gds_api/publishing_api"
14
- require "gds_api/publishing_api_v2"
15
16
  require "gds_api/router"
16
17
  require "gds_api/search"
17
18
  require "gds_api/support"
@@ -139,19 +140,6 @@ module GdsApi
139
140
  )
140
141
  end
141
142
 
142
- # Creates a GdsApi::PublishingApiV2 adapter
143
- #
144
- # This will set a bearer token if a PUBLISHING_API_BEARER_TOKEN environment
145
- # variable is set
146
- #
147
- # @return [GdsApi::PublishingApiV2]
148
- def self.publishing_api_v2(options = {})
149
- GdsApi::PublishingApiV2.new(
150
- Plek.find("publishing-api"),
151
- { bearer_token: ENV["PUBLISHING_API_BEARER_TOKEN"] }.merge(options),
152
- )
153
- end
154
-
155
143
  # Creates a GdsApi::Router adapter for communicating with Router API
156
144
  #
157
145
  # This will set a bearer token if a ROUTER_API_BEARER_TOKEN environment
@@ -136,7 +136,7 @@ class GdsApi::AssetManager < GdsApi::Base
136
136
  #
137
137
  # @raise [HTTPErrorResponse] if the request returns an error
138
138
  def whitehall_asset(legacy_url_path)
139
- get_json("#{base_url}/whitehall_assets/#{Addressable::URI.encode(legacy_url_path)}")
139
+ get_json("#{base_url}/whitehall_assets/#{uri_encode(legacy_url_path)}")
140
140
  end
141
141
 
142
142
  # Updates an asset given a hash with one +file+ attribute
@@ -24,7 +24,8 @@ class GdsApi::Base
24
24
  :put_json,
25
25
  :patch_json,
26
26
  :delete_json,
27
- :get_raw, :get_raw!,
27
+ :get_raw,
28
+ :get_raw!,
28
29
  :put_multipart,
29
30
  :post_multipart
30
31
 
@@ -69,9 +70,9 @@ private
69
70
  param_pairs = params.sort.map { |key, value|
70
71
  case value
71
72
  when Array
72
- value.map { |v|
73
+ value.map do |v|
73
74
  "#{CGI.escape(key.to_s + '[]')}=#{CGI.escape(v.to_s)}"
74
- }
75
+ end
75
76
  else
76
77
  "#{CGI.escape(key.to_s)}=#{CGI.escape(value.to_s)}"
77
78
  end
@@ -79,4 +80,8 @@ private
79
80
 
80
81
  "?#{param_pairs.join('&')}"
81
82
  end
83
+
84
+ def uri_encode(param)
85
+ Addressable::URI.encode(param.to_s)
86
+ end
82
87
  end
@@ -101,7 +101,7 @@ class GdsApi::EmailAlertApi < GdsApi::Base
101
101
  #
102
102
  # @return [nil]
103
103
  def unsubscribe(uuid)
104
- post_json("#{endpoint}/unsubscribe/#{uuid}")
104
+ post_json("#{endpoint}/unsubscribe/#{uri_encode(uuid)}")
105
105
  end
106
106
 
107
107
  # Unsubscribe subscriber from everything
@@ -110,18 +110,19 @@ class GdsApi::EmailAlertApi < GdsApi::Base
110
110
  #
111
111
  # @return [nil]
112
112
  def unsubscribe_subscriber(id)
113
- delete_json("#{endpoint}/subscribers/#{id}")
113
+ delete_json("#{endpoint}/subscribers/#{uri_encode(id)}")
114
114
  end
115
115
 
116
116
  # Subscribe
117
117
  #
118
118
  # @return [Hash] subscription_id
119
- def subscribe(subscriber_list_id:, address:, frequency: "immediately")
119
+ def subscribe(subscriber_list_id:, address:, frequency: "immediately", skip_confirmation_email: false)
120
120
  post_json(
121
121
  "#{endpoint}/subscriptions",
122
122
  subscriber_list_id: subscriber_list_id,
123
123
  address: address,
124
124
  frequency: frequency,
125
+ skip_confirmation_email: skip_confirmation_email,
125
126
  )
126
127
  end
127
128
 
@@ -141,7 +142,7 @@ class GdsApi::EmailAlertApi < GdsApi::Base
141
142
  # subscriber_count
142
143
  # }
143
144
  def get_subscriber_list(slug:)
144
- get_json("#{endpoint}/subscriber-lists/#{slug}")
145
+ get_json("#{endpoint}/subscriber-lists/#{uri_encode(slug)}")
145
146
  end
146
147
 
147
148
  # Get a Subscription
@@ -158,7 +159,7 @@ class GdsApi::EmailAlertApi < GdsApi::Base
158
159
  # source
159
160
  # }
160
161
  def get_subscription(id)
161
- get_json("#{endpoint}/subscriptions/#{id}")
162
+ get_json("#{endpoint}/subscriptions/#{uri_encode(id)}")
162
163
  end
163
164
 
164
165
  # Get the latest Subscription that has the same subscriber_list
@@ -177,7 +178,7 @@ class GdsApi::EmailAlertApi < GdsApi::Base
177
178
  # source
178
179
  # }
179
180
  def get_latest_matching_subscription(id)
180
- get_json("#{endpoint}/subscriptions/#{id}/latest")
181
+ get_json("#{endpoint}/subscriptions/#{uri_encode(id)}/latest")
181
182
  end
182
183
 
183
184
  # Get Subscriptions for a Subscriber
@@ -188,9 +189,9 @@ class GdsApi::EmailAlertApi < GdsApi::Base
188
189
  # @return [Hash] subscriber, subscriptions
189
190
  def get_subscriptions(id:, order: nil)
190
191
  if order
191
- get_json("#{endpoint}/subscribers/#{id}/subscriptions?order=#{order}")
192
+ get_json("#{endpoint}/subscribers/#{uri_encode(id)}/subscriptions?order=#{uri_encode(order)}")
192
193
  else
193
- get_json("#{endpoint}/subscribers/#{id}/subscriptions")
194
+ get_json("#{endpoint}/subscribers/#{uri_encode(id)}/subscriptions")
194
195
  end
195
196
  end
196
197
 
@@ -202,7 +203,7 @@ class GdsApi::EmailAlertApi < GdsApi::Base
202
203
  # @return [Hash] subscriber
203
204
  def change_subscriber(id:, new_address:)
204
205
  patch_json(
205
- "#{endpoint}/subscribers/#{id}",
206
+ "#{endpoint}/subscribers/#{uri_encode(id)}",
206
207
  new_address: new_address,
207
208
  )
208
209
  end
@@ -215,7 +216,7 @@ class GdsApi::EmailAlertApi < GdsApi::Base
215
216
  # @return [Hash] subscription
216
217
  def change_subscription(id:, frequency:)
217
218
  patch_json(
218
- "#{endpoint}/subscriptions/#{id}",
219
+ "#{endpoint}/subscriptions/#{uri_encode(id)}",
219
220
  frequency: frequency,
220
221
  )
221
222
  end
@@ -224,16 +225,14 @@ class GdsApi::EmailAlertApi < GdsApi::Base
224
225
  #
225
226
  # @param [string] address Address to send verification email to
226
227
  # @param [string] destination Path on GOV.UK that subscriber will be emailed
227
- # @param [string, nil] redirect Path on GOV.UK to be encoded into the token for redirecting
228
228
  #
229
229
  # @return [Hash] subscriber
230
230
  #
231
- def send_subscriber_verification_email(address:, destination:, redirect: nil)
231
+ def send_subscriber_verification_email(address:, destination:)
232
232
  post_json(
233
233
  "#{endpoint}/subscribers/auth-token",
234
234
  address: address,
235
235
  destination: destination,
236
- redirect: redirect,
237
236
  )
238
237
  end
239
238
 
@@ -20,8 +20,8 @@ class GdsApi::Imminence < GdsApi::Base
20
20
  end
21
21
 
22
22
  def self.parse_place_hash(place_hash)
23
- location = self.extract_location_hash(place_hash["location"])
24
- address = self.extract_address_hash(place_hash)
23
+ location = extract_location_hash(place_hash["location"])
24
+ address = extract_address_hash(place_hash)
25
25
 
26
26
  place_hash.merge(location).merge(address)
27
27
  end
@@ -31,7 +31,7 @@ class GdsApi::Imminence < GdsApi::Base
31
31
  end
32
32
 
33
33
  def areas_for_postcode(postcode)
34
- url = "#{@endpoint}/areas/#{ERB::Util.url_encode(postcode)}.json"
34
+ url = "#{@endpoint}/areas/#{uri_encode(postcode)}.json"
35
35
  get_json(url)
36
36
  end
37
37
 
@@ -29,7 +29,7 @@ module GdsApi
29
29
  end
30
30
 
31
31
  def self.default_request_with_json_body_headers
32
- self.default_request_headers.merge(self.json_body_headers)
32
+ default_request_headers.merge(json_body_headers)
33
33
  end
34
34
 
35
35
  def self.json_body_headers
@@ -109,7 +109,7 @@ module GdsApi
109
109
  end
110
110
 
111
111
  # If no custom response is given, just instantiate Response
112
- create_response ||= Proc.new { |r| Response.new(r) }
112
+ create_response ||= proc { |r| Response.new(r) }
113
113
  create_response.call(response)
114
114
  end
115
115
 
@@ -177,10 +177,10 @@ module GdsApi
177
177
  ::RestClient::Request.execute(method_params)
178
178
  rescue Errno::ECONNREFUSED => e
179
179
  logger.error loggable.merge(status: "refused", error_message: e.message, error_class: e.class.name, end_time: Time.now.to_f).to_json
180
- raise GdsApi::EndpointNotFound.new("Could not connect to #{url}")
180
+ raise GdsApi::EndpointNotFound, "Could not connect to #{url}"
181
181
  rescue RestClient::Exceptions::Timeout => e
182
182
  logger.error loggable.merge(status: "timeout", error_message: e.message, error_class: e.class.name, end_time: Time.now.to_f).to_json
183
- raise GdsApi::TimedOutException.new
183
+ raise GdsApi::TimedOutException
184
184
  rescue URI::InvalidURIError => e
185
185
  logger.error loggable.merge(status: "invalid_uri", error_message: e.message, error_class: e.class.name, end_time: Time.now.to_f).to_json
186
186
  raise GdsApi::InvalidUrl
@@ -192,10 +192,10 @@ module GdsApi
192
192
  raise
193
193
  rescue Errno::ECONNRESET => e
194
194
  logger.error loggable.merge(status: "connection_reset", error_message: e.message, error_class: e.class.name, end_time: Time.now.to_f).to_json
195
- raise GdsApi::TimedOutException.new
195
+ raise GdsApi::TimedOutException
196
196
  rescue SocketError => e
197
197
  logger.error loggable.merge(status: "socket_error", error_message: e.message, error_class: e.class.name, end_time: Time.now.to_f).to_json
198
- raise GdsApi::SocketErrorException.new
198
+ raise GdsApi::SocketErrorException
199
199
  end
200
200
  end
201
201
  end
@@ -25,7 +25,7 @@ module GdsApi
25
25
  end
26
26
 
27
27
  def has_next_page?
28
- ! page_link("next").nil?
28
+ !page_link("next").nil?
29
29
  end
30
30
 
31
31
  def next_page
@@ -39,7 +39,7 @@ module GdsApi
39
39
  end
40
40
 
41
41
  def has_previous_page?
42
- ! page_link("previous").nil?
42
+ !page_link("previous").nil?
43
43
  end
44
44
 
45
45
  def previous_page
@@ -70,12 +70,12 @@ module GdsApi
70
70
  # point. Note that the responses are stored so subsequent pages will not be
71
71
  # loaded multiple times.
72
72
  def with_subsequent_pages
73
- Enumerator.new { |yielder|
74
- self.each do |i| yielder << i end
73
+ Enumerator.new do |yielder|
74
+ each { |i| yielder << i }
75
75
  if has_next_page?
76
- next_page.with_subsequent_pages.each do |i| yielder << i end
76
+ next_page.with_subsequent_pages.each { |i| yielder << i }
77
77
  end
78
- }
78
+ end
79
79
  end
80
80
 
81
81
  private
@@ -70,40 +70,40 @@ module GdsApi
70
70
 
71
71
  def search_terms(slug)
72
72
  options = {
73
- slug: slug,
74
- transaction: "search-terms",
75
- group_by: "searchKeyword",
76
- collect: "searchUniques:sum",
73
+ slug: slug,
74
+ transaction: "search-terms",
75
+ group_by: "searchKeyword",
76
+ collect: "searchUniques:sum",
77
77
  }
78
78
  statistics(options)
79
79
  end
80
80
 
81
81
  def searches(slug, is_multipart)
82
82
  options = {
83
- slug: slug,
84
- transaction: "search-terms",
85
- group_by: "pagePath",
86
- collect: "searchUniques:sum",
83
+ slug: slug,
84
+ transaction: "search-terms",
85
+ group_by: "pagePath",
86
+ collect: "searchUniques:sum",
87
87
  }
88
88
  statistics(options, is_multipart)
89
89
  end
90
90
 
91
91
  def page_views(slug, is_multipart)
92
92
  options = {
93
- slug: slug,
94
- transaction: "page-statistics",
95
- group_by: "pagePath",
96
- collect: "uniquePageviews:sum",
93
+ slug: slug,
94
+ transaction: "page-statistics",
95
+ group_by: "pagePath",
96
+ collect: "uniquePageviews:sum",
97
97
  }
98
98
  statistics(options, is_multipart)
99
99
  end
100
100
 
101
101
  def problem_reports(slug, is_multipart)
102
102
  options = {
103
- slug: slug,
104
- transaction: "page-contacts",
105
- group_by: "pagePath",
106
- collect: "total:sum",
103
+ slug: slug,
104
+ transaction: "page-contacts",
105
+ group_by: "pagePath",
106
+ collect: "total:sum",
107
107
  }
108
108
  statistics(options, is_multipart)
109
109
  end
@@ -114,11 +114,11 @@ module GdsApi
114
114
  # Backdrop can be found here: https://github.com/alphagov/backdrop
115
115
  def statistics(options, is_multipart = false)
116
116
  params = {
117
- group_by: options[:group_by],
118
- collect: options[:collect],
119
- duration: 42,
120
- period: "day",
121
- end_at: Date.today.to_time.getutc.iso8601,
117
+ group_by: options[:group_by],
118
+ collect: options[:collect],
119
+ duration: 42,
120
+ period: "day",
121
+ end_at: Date.today.to_time.getutc.iso8601,
122
122
  }
123
123
 
124
124
  filter_param = is_multipart ? :filter_by_prefix : :filter_by
@@ -381,7 +381,7 @@ class GdsApi::PublishingApi < GdsApi::Base
381
381
  # @see https://github.com/alphagov/publishing-api/blob/master/doc/api.md#get-v2linkables
382
382
  def get_linkables(document_type: nil)
383
383
  if document_type.nil?
384
- raise ArgumentError.new("Please provide a `document_type`")
384
+ raise ArgumentError, "Please provide a `document_type`"
385
385
  end
386
386
 
387
387
  get_json("#{endpoint}/v2/linkables?document_type=#{document_type}")
@@ -486,7 +486,7 @@ class GdsApi::PublishingApi < GdsApi::Base
486
486
  # publishing_app: 'content-publisher',
487
487
  # rendering_app: 'government-frontend',
488
488
  # }
489
- #)
489
+ # )
490
490
  #
491
491
  # @see https://github.com/alphagov/publishing-api/blob/master/doc/api.md#put-publish-intentbase_path
492
492
  def put_intent(base_path, payload)
@@ -19,7 +19,7 @@ module GdsApi
19
19
  schema_name: options.fetch(:schema_name, "special_route"),
20
20
  title: options.fetch(:title),
21
21
  description: options.fetch(:description, ""),
22
- locale: "en",
22
+ locale: options.fetch(:locale, "en"),
23
23
  details: {},
24
24
  routes: [
25
25
  {
@@ -1,6 +1,5 @@
1
1
  require "json"
2
2
  require "forwardable"
3
- require "rack/cache"
4
3
 
5
4
  module GdsApi
6
5
  # This wraps an HTTP response with a JSON body.
@@ -21,6 +20,77 @@ module GdsApi
21
20
  extend Forwardable
22
21
  include Enumerable
23
22
 
23
+ class CacheControl < Hash
24
+ PATTERN = /([-a-z]+)(?:\s*=\s*([^,\s]+))?,?+/i.freeze
25
+
26
+ def initialize(value = nil)
27
+ parse(value)
28
+ end
29
+
30
+ def public?
31
+ self["public"]
32
+ end
33
+
34
+ def private?
35
+ self["private"]
36
+ end
37
+
38
+ def no_cache?
39
+ self["no-cache"]
40
+ end
41
+
42
+ def no_store?
43
+ self["no-store"]
44
+ end
45
+
46
+ def must_revalidate?
47
+ self["must-revalidate"]
48
+ end
49
+
50
+ def proxy_revalidate?
51
+ self["proxy-revalidate"]
52
+ end
53
+
54
+ def max_age
55
+ self["max-age"].to_i if key?("max-age")
56
+ end
57
+
58
+ def reverse_max_age
59
+ self["r-maxage"].to_i if key?("r-maxage")
60
+ end
61
+ alias_method :r_maxage, :reverse_max_age
62
+
63
+ def shared_max_age
64
+ self["s-maxage"].to_i if key?("r-maxage")
65
+ end
66
+ alias_method :s_maxage, :shared_max_age
67
+
68
+ def to_s
69
+ directives = []
70
+ values = []
71
+
72
+ each do |key, value|
73
+ if value == true
74
+ directives << key
75
+ elsif value
76
+ values << "#{key}=#{value}"
77
+ end
78
+ end
79
+
80
+ (directives.sort + values.sort).join(", ")
81
+ end
82
+
83
+ private
84
+
85
+ def parse(header)
86
+ return if header.nil? || header.empty?
87
+
88
+ header.scan(PATTERN).each do |name, value|
89
+ self[name.downcase] = value || true
90
+ end
91
+ end
92
+ end
93
+
24
94
  def_delegators :to_hash, :[], :"<=>", :each, :dig
25
95
 
26
96
  def initialize(http_response, options = {})
@@ -63,7 +133,7 @@ module GdsApi
63
133
  end
64
134
 
65
135
  def cache_control
66
- @cache_control ||= Rack::Cache::CacheControl.new(headers[:cache_control])
136
+ @cache_control ||= CacheControl.new(headers[:cache_control])
67
137
  end
68
138
 
69
139
  def to_hash
@@ -74,9 +144,13 @@ module GdsApi
74
144
  @parsed_content ||= transform_parsed(JSON.parse(@http_response.body))
75
145
  end
76
146
 
77
- def present?; true; end
147
+ def present?
148
+ true
149
+ end
78
150
 
79
- def blank?; false; end
151
+ def blank?
152
+ false
153
+ end
80
154
 
81
155
  private
82
156
 
@@ -85,7 +159,7 @@ module GdsApi
85
159
 
86
160
  case value
87
161
  when Hash
88
- Hash[value.map { |k, v|
162
+ Hash[value.map do |k, v|
89
163
  # NOTE: Don't bother transforming if the value is nil
90
164
  if k == "web_url" && v
91
165
  # Use relative URLs to route when the web_url value is on the
@@ -98,7 +172,7 @@ module GdsApi
98
172
  else
99
173
  [k, transform_parsed(v)]
100
174
  end
101
- }]
175
+ end]
102
176
  when Array
103
177
  value.map { |v| transform_parsed(v) }
104
178
  else