gds-api-adapters 0.0.52 → 0.1.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.
data/lib/gds_api/base.rb CHANGED
@@ -17,7 +17,8 @@ class GdsApi::Base
17
17
  end
18
18
  end
19
19
 
20
- def_delegators :client, :get_json, :post_json, :put_json, :get_raw
20
+ def_delegators :client, :get_json, :post_json, :post_json!,
21
+ :put_json, :put_json!, :get_raw
21
22
 
22
23
  attr_reader :options
23
24
 
@@ -4,4 +4,20 @@ module GdsApi
4
4
 
5
5
  class TimedOutException < Exception
6
6
  end
7
+
8
+ class HTTPErrorResponse < StandardError
9
+ attr_accessor :code
10
+
11
+ def initialize(code)
12
+ @code = code
13
+ end
14
+ end
15
+
16
+ module ExceptionHandling
17
+ def ignoring(exception, &block)
18
+ yield
19
+ rescue exception
20
+ # Discard the exception
21
+ end
22
+ end
7
23
  end
@@ -6,6 +6,8 @@ require 'lrucache'
6
6
  module GdsApi
7
7
  class JsonClient
8
8
 
9
+ include GdsApi::ExceptionHandling
10
+
9
11
  def self.cache(size=DEFAULT_CACHE_SIZE)
10
12
  @cache ||= LRUCache.new(max_size: size)
11
13
  end
@@ -36,14 +38,32 @@ module GdsApi
36
38
  end
37
39
 
38
40
  def get_json(url)
41
+ ignoring GdsApi::HTTPErrorResponse do
42
+ get_json! url
43
+ end
44
+ end
45
+
46
+ def get_json!(url)
39
47
  @cache[url] ||= do_json_request(Net::HTTP::Get, url)
40
48
  end
41
49
 
42
50
  def post_json(url, params)
51
+ ignoring GdsApi::HTTPErrorResponse do
52
+ post_json! url, params
53
+ end
54
+ end
55
+
56
+ def post_json!(url, params)
43
57
  do_json_request(Net::HTTP::Post, url, params)
44
58
  end
45
59
 
46
60
  def put_json(url, params)
61
+ ignoring GdsApi::HTTPErrorResponse do
62
+ put_json! url, params
63
+ end
64
+ end
65
+
66
+ def put_json!(url, params)
47
67
  do_json_request(Net::HTTP::Put, url, params)
48
68
  end
49
69
 
@@ -67,7 +87,7 @@ module GdsApi
67
87
  end
68
88
  loggable.merge!(status: response.code, end_time: Time.now.to_f, body: body)
69
89
  logger.warn loggable.to_json
70
- nil
90
+ raise GdsApi::HTTPErrorResponse.new(response.code.to_i), body
71
91
  end
72
92
  end
73
93
 
@@ -1,7 +1,11 @@
1
1
  require_relative 'base'
2
2
  require_relative 'panopticon/registerer'
3
+ require_relative 'exceptions'
3
4
 
4
5
  class GdsApi::Panopticon < GdsApi::Base
6
+
7
+ include GdsApi::ExceptionHandling
8
+
5
9
  def all
6
10
  url = base_url + '.json'
7
11
  json = get_json url
@@ -14,11 +18,31 @@ class GdsApi::Panopticon < GdsApi::Base
14
18
  end
15
19
 
16
20
  def create_artefact(artefact)
17
- post_json(base_url + ".json", artefact)
21
+ ignoring GdsApi::HTTPErrorResponse do
22
+ create_artefact! artefact
23
+ end
24
+ end
25
+
26
+ def create_artefact!(artefact)
27
+ post_json!(base_url + ".json", artefact)
28
+ end
29
+
30
+ def put_artefact(id_or_slug, artefact)
31
+ ignoring GdsApi::HTTPErrorResponse do
32
+ put_artefact! id_or_slug, artefact
33
+ end
34
+ end
35
+
36
+ def put_artefact!(id_or_slug, artefact)
37
+ put_json!("#{base_url}/#{id_or_slug}.json", artefact)
18
38
  end
19
39
 
20
40
  def update_artefact(id_or_slug, artefact)
21
- put_json("#{base_url}/#{id_or_slug}.json", artefact)
41
+ self.class.logger.warn(
42
+ "The update_artefact method is deprecated and may be removed in a " +
43
+ "future release. You should use put_artefact instead."
44
+ )
45
+ put_artefact(id_or_slug, artefact)
22
46
  end
23
47
 
24
48
  def curated_lists
@@ -2,7 +2,7 @@ module GdsApi
2
2
  class Panopticon < GdsApi::Base
3
3
  class Registerer
4
4
  attr_accessor :logger, :owning_app, :kind
5
-
5
+
6
6
  def initialize(options)
7
7
  @logger = options[:logger] || GdsApi::Base.logger
8
8
  @owning_app = options[:owning_app]
@@ -10,35 +10,43 @@ module GdsApi
10
10
  @panopticon = options[:panopticon]
11
11
  @platform = options[:platform] || ENV['FACTER_govuk_platform'] || 'development'
12
12
  end
13
-
13
+
14
14
  def record_to_artefact(record)
15
- hash = {slug: record.slug, owning_app: owning_app, kind: kind, name: record.title}
16
- [:need_id, :section].each do |attr_name|
15
+ hash = {
16
+ slug: record.slug,
17
+ owning_app: owning_app,
18
+ kind: kind,
19
+ name: record.title,
20
+ live: record.live
21
+ }
22
+ [:need_id, :section, :indexable_content].each do |attr_name|
17
23
  if record.respond_to? attr_name
18
24
  hash[attr_name] = record.send(attr_name)
19
25
  end
20
26
  end
21
27
  hash
22
28
  end
23
-
29
+
24
30
  # record should respond to #slug and #title, or override #record_to_artefact
25
31
  def register(record)
26
32
  register_artefact(record_to_artefact(record))
27
33
  end
28
-
34
+
29
35
  protected
30
-
36
+
31
37
  def register_artefact(artefact)
32
- logger.info "Checking #{artefact[:slug]}"
33
- existing = panopticon.artefact_for_slug(artefact[:slug])
34
- if ! existing
35
- logger.info "Creating #{artefact[:slug]}"
36
- panopticon.create_artefact(artefact)
37
- elsif existing.owning_app == artefact[:owning_app]
38
- logger.info "Updating #{artefact[:slug]}"
39
- panopticon.update_artefact(artefact[:slug], artefact)
38
+ logger.info "Putting #{artefact[:slug]}"
39
+
40
+ # Error responses here are pretty fatal, so propagate them
41
+ response = panopticon.put_artefact!(artefact[:slug], artefact)
42
+ case response.code
43
+ when 200
44
+ logger.info "Updated #{artefact[:slug]}"
45
+ when 201
46
+ logger.info "Created #{artefact[:slug]}"
40
47
  else
41
- raise "Slug #{artefact[:slug]} already registered to application '#{existing.owning_app}'"
48
+ # Only expect 200 or 201 success codes, but best to have a fallback
49
+ logger.info "Registered #{artefact[:slug]} (code #{response.code})"
42
50
  end
43
51
  end
44
52
 
@@ -48,7 +56,7 @@ module GdsApi
48
56
  }
49
57
  @panopticon ||= GdsApi::Panopticon.new(@platform, options.merge(panopticon_api_credentials))
50
58
  end
51
-
59
+
52
60
  def panopticon_api_credentials
53
61
  Object::const_defined?(:PANOPTICON_API_CREDENTIALS) ? PANOPTICON_API_CREDENTIALS : {}
54
62
  end
@@ -25,23 +25,6 @@ class GdsApi::Publisher < GdsApi::Base
25
25
  end
26
26
  end
27
27
 
28
- def council_for_snac_code(snac)
29
- if json = get_json("#{@endpoint}/local_transactions/find_by_snac?snac=#{snac}")
30
- json.to_hash
31
- else
32
- nil
33
- end
34
- end
35
-
36
- def council_for_name(name)
37
- name = URI.escape(name)
38
- if json = get_json("#{@endpoint}/local_transactions/find_by_council_name?name=#{name}")
39
- json.to_hash
40
- else
41
- nil
42
- end
43
- end
44
-
45
28
  def licences_for_ids(ids)
46
29
  response = get_json("#{@endpoint}/licences.json?ids=#{ids.map(&:to_s).sort.join(',')}")
47
30
  if response
@@ -17,6 +17,11 @@ module GdsApi
17
17
  @parsed ||= JSON.parse(@net_http_response.body)
18
18
  end
19
19
 
20
+ def code
21
+ # Return an integer code for consistency with HTTPErrorResponse
22
+ @net_http_response.code.to_i
23
+ end
24
+
20
25
  def to_ostruct
21
26
  self.class.build_ostruct_recursively(to_hash)
22
27
  end
@@ -31,13 +31,6 @@ module GdsApi
31
31
  stub_request(:get, url).to_return(:status => 404, :body => "", :headers => {})
32
32
  end
33
33
 
34
- def stub_panopticon_default_artefact
35
- stub_request(:get, %r{\A#{PANOPTICON_ENDPOINT}/artefacts}).to_return { |request|
36
- # return a response with only a slug, and set that slug to match the requested artefact slug
37
- {:body => JSON.dump("slug" => request.uri.path.split('/').last.chomp('.json'))}
38
- }
39
- end
40
-
41
34
  end
42
35
  end
43
36
  end
@@ -1,3 +1,3 @@
1
1
  module GdsApi
2
- VERSION = '0.0.52'
2
+ VERSION = '0.1.0'
3
3
  end
@@ -98,14 +98,14 @@ class JsonClientTest < MiniTest::Spec
98
98
  response = @client.put_json(url, payload)
99
99
  assert_equal 2, response.a.b
100
100
  end
101
-
101
+
102
102
  def test_accessing_non_existent_attribute_of_response_returns_nil
103
103
  url = "http://some.endpoint/some.json"
104
104
  stub_request(:put, url).to_return(:body => '{"a":1}', :status => 200)
105
105
  response = @client.put_json(url, {})
106
106
  assert_equal nil, response.does_not_exist
107
107
  end
108
-
108
+
109
109
  def test_response_does_not_claim_to_respond_to_methods_corresponding_to_non_existent_attributes
110
110
  # This mimics the behaviour of OpenStruct
111
111
  url = "http://some.endpoint/some.json"
@@ -113,7 +113,7 @@ class JsonClientTest < MiniTest::Spec
113
113
  response = @client.put_json(url, {})
114
114
  assert ! response.respond_to?(:does_not_exist)
115
115
  end
116
-
116
+
117
117
  def test_a_response_is_always_considered_present_and_not_blank
118
118
  url = "http://some.endpoint/some.json"
119
119
  stub_request(:put, url).to_return(:body => '{"a":1}', :status => 200)
@@ -121,7 +121,7 @@ class JsonClientTest < MiniTest::Spec
121
121
  assert ! response.blank?
122
122
  assert response.present?
123
123
  end
124
-
124
+
125
125
  def test_client_can_use_basic_auth
126
126
  client = GdsApi::JsonClient.new(basic_auth: {user: 'user', password: 'password'})
127
127
 
@@ -23,6 +23,16 @@ class PanopticonApiTest < MiniTest::Unit::TestCase
23
23
  }
24
24
  end
25
25
 
26
+ def registerable_artefact
27
+ {
28
+ slug: 'foo',
29
+ owning_app: 'my-app',
30
+ kind: 'custom-application',
31
+ name: 'MyFoo',
32
+ live: true
33
+ }
34
+ end
35
+
26
36
  def api
27
37
  GdsApi::Panopticon.new('test')
28
38
  end
@@ -93,12 +103,12 @@ class PanopticonApiTest < MiniTest::Unit::TestCase
93
103
 
94
104
  api.update_artefact(1, basic_artefact)
95
105
  end
96
-
106
+
97
107
  def test_can_register_new_artefacts_en_masse
98
- artefact = {slug: 'foo', owning_app: 'my-app', kind: 'custom-application', name: 'MyFoo'}
99
108
  r = GdsApi::Panopticon::Registerer.new(platform: "test", owning_app: 'my-app')
109
+ artefact = registerable_artefact()
100
110
  panopticon_has_no_metadata_for('foo')
101
-
111
+
102
112
  stub_request(:put, "#{PANOPTICON_ENDPOINT}/artefacts/foo.json")
103
113
  .with(body: artefact.to_json)
104
114
  .to_return(body: artefact.merge(id: 1).to_json)
@@ -107,13 +117,13 @@ class PanopticonApiTest < MiniTest::Unit::TestCase
107
117
  stub_request(:post, url)
108
118
  .with(body: artefact.to_json)
109
119
  .to_return(body: artefact.merge(id: 1).to_json)
110
-
120
+
111
121
  record = OpenStruct.new(artefact.merge(title: artefact[:name]))
112
122
  r.register(record)
113
123
  end
114
124
 
115
125
  def test_can_register_existing_artefacts_en_masse
116
- artefact = {slug: 'foo', owning_app: 'my-app', kind: 'custom-application', name: 'MyFoo'}
126
+ artefact = registerable_artefact()
117
127
  r = GdsApi::Panopticon::Registerer.new(platform: "test", owning_app: 'my-app')
118
128
 
119
129
  panopticon_has_metadata(artefact)
@@ -138,48 +138,5 @@ describe GdsApi::Publisher do
138
138
 
139
139
  assert_equal nil, api.licences_for_ids([123,124])
140
140
  end
141
-
142
- it "should return nil if a council snac code is not found" do
143
- stub_request(:get, "#{PUBLISHER_ENDPOINT}/local_transactions/find_by_snac?snac=bloop").
144
- with(:headers => GdsApi::JsonClient::REQUEST_HEADERS).
145
- to_return(:status => 404, :body => " ", :headers => {})
146
-
147
- assert_equal nil, api.council_for_snac_code("bloop")
148
- end
149
-
150
- it "should return a council hash for a snac code" do
151
- stub_request(:get, "#{PUBLISHER_ENDPOINT}/local_transactions/find_by_snac?snac=AA00").
152
- with(:headers => GdsApi::JsonClient::REQUEST_HEADERS).
153
- to_return(:status => 200, :body => '{"name": "Some Council", "snac": "AA00"}', :headers => {})
154
-
155
- expected = {"name" => "Some Council", "snac" => "AA00"}
156
- assert_equal expected, api.council_for_snac_code("AA00")
157
- end
158
-
159
- it "should return nil if a council name is not found" do
160
- stub_request(:get, "#{PUBLISHER_ENDPOINT}/local_transactions/find_by_council_name?name=bloop").
161
- with(:headers => GdsApi::JsonClient::REQUEST_HEADERS).
162
- to_return(:status => 404, :body => " ", :headers => {})
163
-
164
- assert_equal nil, api.council_for_name("bloop")
165
- end
166
-
167
- it "should return a council hash for a mixed case council name" do
168
- stub_request(:get, "#{PUBLISHER_ENDPOINT}/local_transactions/find_by_council_name?name=Some%20Council").
169
- with(:headers => GdsApi::JsonClient::REQUEST_HEADERS).
170
- to_return(:status => 200, :body => '{"name": "Some Council", "snac": "AA00"}', :headers => {})
171
-
172
- expected = {"name" => "Some Council", "snac" => "AA00"}
173
- assert_equal expected, api.council_for_name("Some Council")
174
- end
175
-
176
- it "should return a council hash for a lowercase council name" do
177
- stub_request(:get, "#{PUBLISHER_ENDPOINT}/local_transactions/find_by_council_name?name=some%20council").
178
- with(:headers => GdsApi::JsonClient::REQUEST_HEADERS).
179
- to_return(:status => 200, :body => '{"name": "Some Council", "snac": "AA00"}', :headers => {})
180
-
181
- expected = {"name" => "Some Council", "snac" => "AA00"}
182
- assert_equal expected, api.council_for_name("some council")
183
- end
184
141
  end
185
142
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: gds-api-adapters
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.0.52
5
+ version: 0.1.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - James Stewart
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2012-07-18 00:00:00 Z
13
+ date: 2012-06-29 00:00:00 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: plek
@@ -143,35 +143,35 @@ extensions: []
143
143
  extra_rdoc_files: []
144
144
 
145
145
  files:
146
- - lib/gds_api/version.rb
147
- - lib/gds_api/publisher.rb
148
- - lib/gds_api/panopticon/registerer.rb
146
+ - lib/gds_api/helpers.rb
147
+ - lib/gds_api/base.rb
148
+ - lib/gds_api/part_methods.rb
149
+ - lib/gds_api/exceptions.rb
149
150
  - lib/gds_api/typhoeus_client.rb
150
151
  - lib/gds_api/imminence.rb
152
+ - lib/gds_api/publisher.rb
151
153
  - lib/gds_api/contactotron.rb
152
- - lib/gds_api/test_helpers/publisher.rb
154
+ - lib/gds_api/panopticon.rb
155
+ - lib/gds_api/version.rb
156
+ - lib/gds_api/oauth2_client.rb
153
157
  - lib/gds_api/test_helpers/imminence.rb
158
+ - lib/gds_api/test_helpers/publisher.rb
154
159
  - lib/gds_api/test_helpers/contactotron.rb
155
160
  - lib/gds_api/test_helpers/panopticon.rb
156
161
  - lib/gds_api/test_helpers/json_client_helper.rb
157
- - lib/gds_api/base.rb
158
- - lib/gds_api/json_client.rb
159
162
  - lib/gds_api/response.rb
160
- - lib/gds_api/panopticon.rb
161
- - lib/gds_api/core-ext/openstruct.rb
162
- - lib/gds_api/oauth2_client.rb
163
- - lib/gds_api/part_methods.rb
163
+ - lib/gds_api/panopticon/registerer.rb
164
164
  - lib/gds_api/needotron.rb
165
- - lib/gds_api/exceptions.rb
166
- - lib/gds_api/helpers.rb
165
+ - lib/gds_api/json_client.rb
166
+ - lib/gds_api/core-ext/openstruct.rb
167
167
  - README.md
168
168
  - Rakefile
169
- - test/contactotron_api_test.rb
170
- - test/panopticon_api_test.rb
171
- - test/publisher_api_test.rb
172
- - test/json_client_test.rb
173
169
  - test/gds_api_base_test.rb
170
+ - test/json_client_test.rb
174
171
  - test/test_helper.rb
172
+ - test/publisher_api_test.rb
173
+ - test/panopticon_api_test.rb
174
+ - test/contactotron_api_test.rb
175
175
  homepage: http://github.com/alphagov/gds-api-adapters
176
176
  licenses: []
177
177
 
@@ -185,7 +185,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
185
185
  requirements:
186
186
  - - ">="
187
187
  - !ruby/object:Gem::Version
188
- hash: 2947988208479081559
188
+ hash: 3070109834685786037
189
189
  segments:
190
190
  - 0
191
191
  version: "0"
@@ -194,7 +194,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
194
194
  requirements:
195
195
  - - ">="
196
196
  - !ruby/object:Gem::Version
197
- hash: 2947988208479081559
197
+ hash: 3070109834685786037
198
198
  segments:
199
199
  - 0
200
200
  version: "0"
@@ -206,9 +206,9 @@ signing_key:
206
206
  specification_version: 3
207
207
  summary: Adapters to work with GDS APIs
208
208
  test_files:
209
- - test/contactotron_api_test.rb
210
- - test/panopticon_api_test.rb
211
- - test/publisher_api_test.rb
212
- - test/json_client_test.rb
213
209
  - test/gds_api_base_test.rb
210
+ - test/json_client_test.rb
214
211
  - test/test_helper.rb
212
+ - test/publisher_api_test.rb
213
+ - test/panopticon_api_test.rb
214
+ - test/contactotron_api_test.rb