postcodes 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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4ca63fb1e521a07e8d555646be9f4133ff741fa8
4
+ data.tar.gz: 5883e86c9cce783fbc293d26dfcd7fcde377abb1
5
+ SHA512:
6
+ metadata.gz: df0c13a6702cc09f0db334b01cd9368d6b04fabf3bec8b0b6f8071f94ccc672e702aed5803061e1b8c57713596cd81e6245c08c7c5e74fdb8e0f09c3ea6d2f37
7
+ data.tar.gz: 27a3591660a99b014685dc234bf4ab09469e23372ac1a9ced7641b5a36002dae88327e943c41000c45ed34837206278ccb5f9e7f5640350afb03cf17e0ce7cfc
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source "https://rubygems.org"
2
+ gemspec
@@ -0,0 +1,49 @@
1
+ # Open Postcodes API Ruby Wrapper
2
+
3
+ Retrieve a list of addresses for any postcode in the United Kingdom using the Open Postcodes API.
4
+
5
+ ## Getting Started
6
+
7
+ __Installation__
8
+
9
+ ```bash
10
+ gem install postcodes
11
+ ```
12
+
13
+ __Get an API Key__
14
+
15
+ Get a key at [Open Postcodes](https://openpostcodes.com), then try out our service with our testing postcodes e.g. 'XA1 0XX'
16
+
17
+ __Implement it__
18
+
19
+ You can complete a full address lookup with just a couple of lines of Ruby.
20
+
21
+ ```ruby
22
+ require 'postcodes'
23
+
24
+ Postcodes.api_key = "your_key_here"
25
+
26
+ postcode = Postcodes::Postcode.lookup "XA1 0XX"
27
+
28
+ # postcode.addresses =>
29
+ #
30
+ # [
31
+ # {
32
+ # :postcode=>"XA1 0XX",
33
+ # :post_town=>"LONDON",
34
+ # :line_1=>"The Pavilion",
35
+ # :line_2=>"Oaks Avenue",
36
+ # :line_3=>""
37
+ # },
38
+ # ... and so on
39
+ ```
40
+
41
+ ## Registering
42
+
43
+ Open Postcodes provides street level address data for website, mobile and desktop applications at a competitive price.
44
+
45
+ We charge _1p_ per public lookup; take a look at our [pricing](https://openpostcodes.com/pricing)
46
+
47
+ ## Documentation
48
+
49
+ More in-depth documentation can be found [here](https://openpostcodes.com/documentation#examples-ruby)
@@ -0,0 +1,94 @@
1
+ require 'rest-client'
2
+ require 'uri'
3
+ require 'multi_json'
4
+ require 'cgi'
5
+ require 'postcodes/postcode'
6
+ require 'postcodes/util'
7
+ require 'postcodes/errors'
8
+
9
+ module Postcodes
10
+ @base_url = 'https://api.openpostcodes.com'
11
+ @version = '1'
12
+
13
+ class << self
14
+ attr_accessor :api_key, :base_url, :version
15
+ end
16
+
17
+ def self.request(method, path, params = {})
18
+ unless @api_key
19
+ raise Postcodes::AuthenticationError.new('No API Key provided. ' +
20
+ 'Set your API key using Postcodes.api_key = #your_key')
21
+ end
22
+
23
+ url = URI.parse(resource_url(path))
24
+ params.merge! api_key: @api_key
25
+ url.query = Util.merge_params(params)
26
+ request_options = {
27
+ method: method.downcase.to_sym,
28
+ url: url.to_s
29
+ }
30
+
31
+ begin
32
+ response = generate_request(request_options)
33
+ rescue RestClient::ExceptionWithResponse => error
34
+ if rcode = error.http_code && rbody = error.http_body
35
+ handle_error(rcode, rbody)
36
+ else
37
+ handle_client_error(error)
38
+ end
39
+ rescue RestClient::Exception, Errno::ECONNREFUSED => error
40
+ handle_client_error(e)
41
+ end
42
+ parse response.body
43
+ end
44
+
45
+ private
46
+
47
+ def self.resource_url(path='')
48
+ URI.escape "#{@base_url}/v#{@version}/#{path}"
49
+ end
50
+
51
+ def self.generate_request(options)
52
+ RestClient::Request.execute(options)
53
+ end
54
+
55
+ def self.parse(response)
56
+ begin
57
+ Util.keys_to_sym MultiJson.load(response)
58
+ rescue MultiJson::DecodeError => e
59
+ raise handle_client_error(e)
60
+ end
61
+ end
62
+
63
+ def self.handle_error(http_code, http_body)
64
+ error = parse http_body
65
+
66
+ opc_code, opc_message = error[:code], error[:message]
67
+
68
+ case opc_code
69
+ when 4010
70
+ raise AuthenticationError.new opc_message, http_code, http_body, opc_code
71
+ when 4011
72
+ raise RefererExcludedError.new opc_message, http_code, http_body, opc_code
73
+ when 4020
74
+ raise TokenExhaustedError.new opc_message, http_code, http_body, opc_code
75
+ when 4021
76
+ raise LimitReachedError.new opc_message, http_code, http_body, opc_code
77
+ when 4040
78
+ raise ResourceNotFoundError.new opc_message, http_code, http_body, opc_code
79
+ when 4220
80
+ raise InvalidInputError.new opc_message, http_code, http_body, opc_code
81
+ else
82
+ raise PostcodesError.new opc_message, http_code, http_body, opc_code
83
+ end
84
+ end
85
+
86
+ def self.handle_client_error(error)
87
+ raise PostcodesError.new("Unexpected error occurred: #{error.message})")
88
+ end
89
+
90
+ def self.general_error(response_code, response_body)
91
+ PostcodesError.new "Invalid response object", response_code, response_body
92
+ end
93
+
94
+ end
@@ -0,0 +1,39 @@
1
+ module Postcodes
2
+ class PostcodesError < StandardError
3
+ attr_reader :message
4
+ attr_reader :http_code
5
+ attr_reader :http_body
6
+ attr_reader :response_code
7
+
8
+ def initialize(message = nil, http_code = nil, http_body = nil, response_code = nil)
9
+ @message = message
10
+ @http_code = http_code
11
+ @http_body = http_body
12
+ @response_code = response_code
13
+ end
14
+
15
+ def to_s
16
+ status = @http_code.nil? ? "" : "#{@http_code} error."
17
+ opc_code = @response_code.nil ? "" : "(#{@response_code})"
18
+ "#{status} error. (#{opc_code}) #{message}"
19
+ end
20
+ end
21
+
22
+ class AuthenticationError < PostcodesError
23
+ end
24
+
25
+ class RefererExcludedError < PostcodesError
26
+ end
27
+
28
+ class TokenExhaustedError < PostcodesError
29
+ end
30
+
31
+ class LimitReachedError < PostcodesError
32
+ end
33
+
34
+ class ResourceNotFoundError < PostcodesError
35
+ end
36
+
37
+ class InvalidInputError < PostcodesError
38
+ end
39
+ end
@@ -0,0 +1,35 @@
1
+ module Postcodes
2
+ class Postcode
3
+
4
+ attr_reader :postcode_data, :postcode, :addresses
5
+
6
+ def initialize(postcode = nil, postcode_data = nil)
7
+ @raw = postcode_data
8
+ @addresses = (postcode_data.nil? || postcode_data[:result].nil?) ? [] : postcode_data[:result]
9
+ @postcode = postcode
10
+ end
11
+
12
+ def self.lookup(postcode)
13
+ begin
14
+ response = Postcodes.request :get, "postcodes/#{postcode}"
15
+ rescue Postcodes::ResourceNotFoundError => error
16
+ raise error unless error.response_code == 4040
17
+ response = nil
18
+ end
19
+ new postcode, response
20
+ end
21
+
22
+ def empty?
23
+ @raw.nil?
24
+ end
25
+
26
+ def addresses
27
+ @addresses
28
+ end
29
+
30
+ def to_s
31
+ addresses.to_s
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,29 @@
1
+ module Postcodes
2
+ class Util
3
+
4
+ def self.merge_params(hash)
5
+ result = []
6
+ hash.each do |key, value|
7
+ result << "#{CGI.escape(key.to_s)}=#{CGI.escape(value)}"
8
+ end
9
+ result.join("&")
10
+ end
11
+
12
+ def self.keys_to_sym(object)
13
+ case object
14
+ when Hash
15
+ temp = {}
16
+ object.each do |key, value|
17
+ key = (key.to_sym rescue key) || key
18
+ temp[key] = keys_to_sym(value)
19
+ end
20
+ temp
21
+ when Array
22
+ object.map { |elem| keys_to_sym(elem) }
23
+ else
24
+ object
25
+ end
26
+ end
27
+
28
+ end
29
+ end
metadata ADDED
@@ -0,0 +1,79 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: postcodes
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Open Postcodes
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-06-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rest-client
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: multi_json
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: 1.7.9
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: 1.7.9
41
+ description: Open Postcodes provides a postcode lookup API for UK addresses. More
42
+ information https://openpostcodes.com
43
+ email:
44
+ - support@openpostcodes.com
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - Gemfile
50
+ - README.md
51
+ - lib/postcodes.rb
52
+ - lib/postcodes/errors.rb
53
+ - lib/postcodes/postcode.rb
54
+ - lib/postcodes/util.rb
55
+ homepage: https://openpostcodes.com
56
+ licenses:
57
+ - Public Domain
58
+ metadata: {}
59
+ post_install_message:
60
+ rdoc_options: []
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - '>='
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ requirements:
70
+ - - '>='
71
+ - !ruby/object:Gem::Version
72
+ version: '0'
73
+ requirements: []
74
+ rubyforge_project:
75
+ rubygems_version: 2.0.14
76
+ signing_key:
77
+ specification_version: 4
78
+ summary: A wrapper for the OpenPostcodes.com API
79
+ test_files: []