loqate 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e1f1396b79c0115311d766dd1b8fb7f4b0325596d27293d1b1d4af7c0d3d4a29
4
- data.tar.gz: e2a275316138017ec971b0a4412e8cc92a872983a523067c33c1ea2c88785de3
3
+ metadata.gz: fff6b4e7b798fed1a00eb2acfa53ffd3997820f815e1ef780ab46d4e8efbb68b
4
+ data.tar.gz: d442998133eaafc167db8a823b87703021bbf72c061237cac7a0dbb659d9a271
5
5
  SHA512:
6
- metadata.gz: abf8817900f777554ded8b558dd43e4f94ebead001fb53c9ac012e8d462f7b4c3926e86a00ea1ac3d5b9230376c19af03931d08c4a0c684bf137369dd8ce332b
7
- data.tar.gz: 470d80e084b048173e3ae34d230227308c2855fbb2fa26be93897464ba9c9fd9a0490f0ee9062302107315f4ecb168db50c39e6799af009e492af223b2dad2b2
6
+ metadata.gz: d57781e89b7743e9c315d97e821cb31d56b0a1b2458cf1d2a640908e9d6e9bd45f8d64f155b63ccd2b704fa1b1b9b71bf700acd7c10ac08afcdf3c1e99e62020
7
+ data.tar.gz: 794e2d39014cc609fb708989785c74c551ad895bff4565b2f00cc67351353587b2bf3974c91fec54b53e02a7fb44668529c79058318444e8f5bbd00ba1985edd
@@ -47,6 +47,7 @@ rules:
47
47
  - Loqate::Result::Failure#failure?
48
48
  - Loqate::Result#code
49
49
  - Loqate::Result#value
50
+ - Loqate::Result::Failure#error
50
51
  ReturnTag:
51
52
  enabled: true
52
53
  exclude:
@@ -60,9 +61,9 @@ rules:
60
61
  - Loqate::AddressGateway#client
61
62
  - Loqate::AddressGateway#mapper
62
63
  - Loqate::AddressGateway#error_mapper
63
- - Loqate::AddressGateway#build_errors_from
64
- - Loqate::AddressGateway#build_address_from
65
- - Loqate::AddressGateway#build_detailed_addresses_from
64
+ - Loqate::AddressGateway#build_error_from
65
+ - Loqate::AddressGateway#build_addresses_from
66
+ - Loqate::AddressGateway#build_detailed_address_from
66
67
  - Loqate::Client#configuration
67
68
  - Loqate::Client#authenticate_params
68
69
  - Loqate::Client#format_params
@@ -73,6 +74,7 @@ rules:
73
74
  - Loqate::Util#underscore
74
75
  - Loqate::Error#attributes
75
76
  - Loqate::Gateway#client
77
+ - Loqate::Result::Failure#error
76
78
  Summary::Presence:
77
79
  enabled: true
78
80
  exclude:
@@ -86,9 +88,9 @@ rules:
86
88
  - Loqate::AddressGateway#client
87
89
  - Loqate::AddressGateway#mapper
88
90
  - Loqate::AddressGateway#error_mapper
89
- - Loqate::AddressGateway#build_errors_from
90
- - Loqate::AddressGateway#build_address_from
91
- - Loqate::AddressGateway#build_detailed_addresses_from
91
+ - Loqate::AddressGateway#build_error_from
92
+ - Loqate::AddressGateway#build_addresses_from
93
+ - Loqate::AddressGateway#build_detailed_address_from
92
94
  - Loqate::Client#configuration
93
95
  - Loqate::Client#authenticate_params
94
96
  - Loqate::Client#format_params
@@ -96,6 +98,7 @@ rules:
96
98
  - Loqate::DetailedAddress#==
97
99
  - Loqate::Error#attributes
98
100
  - Loqate::Gateway#client
101
+ - Loqate::Result::Failure#error
99
102
  Summary::Length:
100
103
  enabled: false
101
104
  Summary::Delimiter:
@@ -4,6 +4,21 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5
5
  and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [0.3.0] - 2018-11-10
8
+ ### Changed
9
+ - `address.retrieve` and `address.find` return a single error, not an array with a single item
10
+ - `address.retrieve` returns a single address, not an array of addresses
11
+ - `Loqate::Error` inherits from `StandardError` so that it can be raised as an exception
12
+ - Improved the documentation of `Success` and `Failure`
13
+
14
+ ## Added
15
+ - `find!` to find an address or raise an exception
16
+ - `retrieve!` to retrieve the details of an address or raise an exception
17
+ - Aliased `Failure#value` to `Failure#error`
18
+
19
+ ## Fixed
20
+ - Fixed the documentation of `AddressGateway`
21
+
7
22
  ## [0.2.0] - 2018-10-31
8
23
  ### Added
9
24
  - VCR and WebMock to record HTTP interactions
@@ -20,4 +35,5 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
20
35
  - Initial core functionality
21
36
  - Codebase maintenance tools
22
37
 
23
- [0.2.0]: https://github.com/wilsonsilva/memoria/compare/v0.1.0...v0.2.0
38
+ [0.3.0]: https://github.com/wilsonsilva/loqate/compare/v0.2.0...v0.3.0
39
+ [0.2.0]: https://github.com/wilsonsilva/loqate/compare/v0.1.0...v0.2.0
data/README.md CHANGED
@@ -38,7 +38,41 @@ To get started, initialize an API gateway with [your API key](https://account.lo
38
38
  gateway = Loqate::Gateway.new(api_key: '<YOUR_API_KEY>')
39
39
  ```
40
40
 
41
- Every call to a gateway method will return a `Loqate::Result` object, which will respond to `success?` and `failure?`.
41
+ ### Bang Methods
42
+
43
+ Most methods have a bang and a non-bang version (e.g. `gateway.address.find` and `gateway.address.find!`).
44
+ The non-bang version will either return a `Loqate::Success` or an `Loqate::Failure`. The bang version will
45
+ either return the desired resource, or it will raise an exception.
46
+
47
+ #### Example of using non-bang method
48
+
49
+ ```ruby
50
+ result = gateway.address.find(text: 'EC1Y 8AF', country: 'GB', limit: 5)
51
+
52
+ if result.success?
53
+ addresses = result.value
54
+ addresses.first.id # => 'GB|RM|B|8144611'
55
+ else
56
+ error = result.error
57
+ puts "Error retrieving the address: #{error.description}. Resolution: #{error.resolution}"
58
+ end
59
+
60
+ result.failure? # => false
61
+ ```
62
+
63
+ #### Example of using bang method
64
+
65
+ ```ruby
66
+ begin
67
+ addresses = gateway.address.find!(text: 'EC1Y 8AF', country: 'GB', limit: 5)
68
+ addresses.first.id # => 'GB|RM|B|8144611'
69
+ rescue Loqate::Error => e
70
+ puts "Error retrieving the address: #{e.description}. Resolution: #{e.resolution}"
71
+ end
72
+ ```
73
+
74
+ It is recommended that you use the bang methods when you assume that the data is valid and do not expect validations
75
+ to fail. Otherwise, use the non-bang methods.
42
76
 
43
77
  ### Address API
44
78
 
@@ -56,9 +90,6 @@ selection.
56
90
  ```ruby
57
91
  result = gateway.address.find(text: 'EC1Y 8AF', country: 'GB', limit: 5)
58
92
 
59
- result.success? # => true
60
- result.failure? # => false
61
-
62
93
  addresses = result.value
63
94
  addresses.first.id # => 'GB|RM|B|8144611'
64
95
  ```
@@ -68,15 +99,10 @@ addresses.first.id # => 'GB|RM|B|8144611'
68
99
  ```ruby
69
100
  result = gateway.address.retrieve(id: 'GB|RM|B|8144611')
70
101
 
71
- result.success? # => true
72
- result.failure? # => false
73
-
74
- addresses = result.value
75
- address = addresses.first
76
-
77
- address.city # 'London'
78
- address.line1 # '148 Warner Road'
79
- address.postal_code # 'E17 7EA'
102
+ address = result.value
103
+ address.city # 'London'
104
+ address.line1 # '148 Warner Road'
105
+ address.postal_code # 'E17 7EA'
80
106
  ```
81
107
 
82
108
  ## Development
data/ROADMAP.md CHANGED
@@ -7,6 +7,7 @@
7
7
  - [ ] Logging
8
8
  - [x] Domain error handling
9
9
  - [x] Configuration
10
+ - [ ] Unwrap request results
10
11
  - [ ] Validate request parameters
11
12
  - [ ] API/Service versioning
12
13
  - [ ] Integration with RSpec
@@ -46,33 +46,79 @@ module Loqate
46
46
  # @example Retrieving an address in the UK
47
47
  # address = address_gateway.find(countries: 'GB', text: 'Scrubs Lane')
48
48
  #
49
- # @return [Array<Address>] A list of addresses
49
+ # @return [Result] A result wrapping a list of addresses
50
50
  #
51
51
  def find(options)
52
52
  response = client.get(FIND_ENDPOINT, options)
53
53
 
54
- response.errors? && build_errors_from(response.items) || build_address_from(response.items)
54
+ response.errors? && build_error_from(response.items.first) || build_addresses_from(response.items)
55
55
  end
56
56
 
57
57
  # Returns the full address details based on the id.
58
58
  #
59
59
  # @param [Hash] options The options to retrieve the address.
60
60
  # @option options [String] :id The Id from a Find method to retrieve the details for.
61
- # @option options [String] :field_1_format a.
62
- # @option options [String] :field_2_format b.
63
- # @option options [String] :field_3_format c.
64
- # @option options [String] :field_4_format d.
65
- # @option options [String] :field_5_format e.
61
+ # @option options [String] :field_1_format Format of a custom address field.
62
+ # @option options [String] :field_2_format Format of a custom address field.
63
+ # @option options [String] :field_3_format Format of a custom address field.
64
+ # @option options [String] :field_4_format Format of a custom address field.
65
+ # @option options [String] :field_5_format Format of a custom address field.
66
66
  #
67
67
  # @example Retrieving the details of an address
68
68
  # detailed_address = gateway.retrieve(id: 'GB|RM|ENG|6RB-NW10')
69
69
  #
70
- # @return [Array<DetailedAddress>] A list of detailed addresses
70
+ # @return [Result] A result wrapping a detailed address
71
71
  #
72
72
  def retrieve(options)
73
73
  response = client.get(RETRIEVE_ENDPOINT, options)
74
74
 
75
- response.errors? && build_errors_from(response.items) || build_detailed_addresses_from(response.items)
75
+ response.errors? && build_error_from(response.items.first) || build_detailed_address_from(response.items.first)
76
+ end
77
+
78
+ # Find addresses and places.
79
+ #
80
+ # @param [Hash] options The options to find an address or a list of addresses.
81
+ # @option options [String] :text The search text to find. Ideally a postcode or the start of the address.
82
+ # @option options [String] countries A comma separated list of ISO 2 or 3 character country codes to limit
83
+ # the search within.
84
+ # @option options [String] origin A starting location for the search. This can be the name or ISO 2 or 3 character
85
+ # code of a country, WGS84 coordinates (comma separated) or IP address to search from.
86
+ # @option options [String] container A container for the search. This should only be another Id previously returned
87
+ # from this service when the Type of the result was not 'Address'.
88
+ # @option options [Integer] limit The maximum number of results to return.
89
+ # @option options [String] language The preferred language for results. This should be a 2 or 4 character language
90
+ # code e.g. (en, fr, en-gb, en-us etc).
91
+ #
92
+ # @example Retrieving addresses in the UK
93
+ # addresses = address_gateway.find!(countries: 'GB', text: 'Scrubs Lane')
94
+ #
95
+ # @raise [Error] If the result is not a success
96
+ #
97
+ # @return [Array<Address>] A list of addresses
98
+ #
99
+ def find!(options)
100
+ unwrap_result_or_raise { find(options) }
101
+ end
102
+
103
+ # Returns the full address details based on the id.
104
+ #
105
+ # @param [Hash] options The options to retrieve the address.
106
+ # @option options [String] :id The Id from a Find method to retrieve the details for.
107
+ # @option options [String] :field_1_format Format of a custom address field.
108
+ # @option options [String] :field_2_format Format of a custom address field.
109
+ # @option options [String] :field_3_format Format of a custom address field.
110
+ # @option options [String] :field_4_format Format of a custom address field.
111
+ # @option options [String] :field_5_format Format of a custom address field.
112
+ #
113
+ # @example Retrieving the details of an address
114
+ # detailed_address = gateway.retrieve!(id: 'GB|RM|ENG|6RB-NW10')
115
+ #
116
+ # @raise [Error] If the result is not a success
117
+ #
118
+ # @return [DetailedAddress] A detailed address
119
+ #
120
+ def retrieve!(options)
121
+ unwrap_result_or_raise { retrieve(options) }
76
122
  end
77
123
 
78
124
  private
@@ -81,20 +127,20 @@ module Loqate
81
127
  attr_reader :client, :mapper, :error_mapper
82
128
 
83
129
  # @api private
84
- def build_errors_from(items)
85
- errors = error_mapper.map(items)
86
- Failure(errors)
130
+ def build_error_from(item)
131
+ error = error_mapper.map_one(item)
132
+ Failure(error)
87
133
  end
88
134
 
89
135
  # @api private
90
- def build_address_from(items)
136
+ def build_addresses_from(items)
91
137
  address = mapper.map(items, Address)
92
138
  Success(address)
93
139
  end
94
140
 
95
141
  # @api private
96
- def build_detailed_addresses_from(items)
97
- detailed_address = mapper.map(items, DetailedAddress)
142
+ def build_detailed_address_from(item)
143
+ detailed_address = mapper.map_one(item, DetailedAddress)
98
144
  Success(detailed_address)
99
145
  end
100
146
  end
@@ -1,6 +1,6 @@
1
1
  module Loqate
2
2
  # Generic error returned from an API call
3
- class Error
3
+ class Error < StandardError
4
4
  # Unique identifier for the error
5
5
  #
6
6
  # @return [Integer]
@@ -33,6 +33,8 @@ module Loqate
33
33
  # @param [String] resolution How to solve the error
34
34
  #
35
35
  def initialize(id:, description:, cause:, resolution:)
36
+ super(description)
37
+
36
38
  @id = id
37
39
  @cause = cause
38
40
  @resolution = resolution
@@ -14,12 +14,18 @@ module Loqate
14
14
  # @return [Array<Error>] An array of errors
15
15
  #
16
16
  def map(items)
17
- items.map do |item|
18
- attributes = item.transform_keys { |attribute| Util.underscore(attribute) }
19
- attributes[:id] = attributes.delete(:error).to_i
17
+ items.map { |item| map_one(item) }
18
+ end
19
+
20
+ # Creates an error from an API response
21
+ #
22
+ # @return [Error] A concrete instance of Error
23
+ #
24
+ def map_one(item)
25
+ attributes = item.transform_keys { |attribute| Util.underscore(attribute) }
26
+ attributes[:id] = attributes.delete(:error).to_i
20
27
 
21
- Loqate::Error.new(attributes)
22
- end
28
+ Loqate::Error.new(attributes)
23
29
  end
24
30
  end
25
31
  end
@@ -15,10 +15,19 @@ module Loqate
15
15
  # @return An array of objects of the given class
16
16
  #
17
17
  def map(items, object_class)
18
- items.map do |item|
19
- attributes = item.transform_keys { |attribute| Util.underscore(attribute) }
20
- object_class.new(attributes)
21
- end
18
+ items.map { |item| map_one(item, object_class) }
19
+ end
20
+
21
+ # Creates a single object from an API response. The object will be an instance of +object_class+.
22
+ #
23
+ # @param [Class] object_class Class of the final object
24
+ # @param [Hash] item Attributes to instantiate the final object
25
+ #
26
+ # @return An object of the given class
27
+ #
28
+ def map_one(item, object_class)
29
+ attributes = item.transform_keys { |attribute| Util.underscore(attribute) }
30
+ object_class.new(attributes)
22
31
  end
23
32
  end
24
33
  end
@@ -31,7 +31,7 @@ module Loqate
31
31
  class Success < Result
32
32
  # Always true
33
33
  #
34
- # @return [Boolean]
34
+ # @return [TrueClass]
35
35
  #
36
36
  def success?
37
37
  true
@@ -39,7 +39,7 @@ module Loqate
39
39
 
40
40
  # Always false
41
41
  #
42
- # @return [Boolean]
42
+ # @return [FalseClass]
43
43
  #
44
44
  def failure?
45
45
  false
@@ -50,7 +50,7 @@ module Loqate
50
50
  class Failure < Result
51
51
  # Always false
52
52
  #
53
- # @return [Boolean]
53
+ # @return [FalseClass]
54
54
  #
55
55
  def success?
56
56
  false
@@ -58,11 +58,13 @@ module Loqate
58
58
 
59
59
  # Always true
60
60
  #
61
- # @return [Boolean]
61
+ # @return [TrueClass]
62
62
  #
63
63
  def failure?
64
64
  true
65
65
  end
66
+
67
+ alias error value
66
68
  end
67
69
 
68
70
  # Utility methods to conveniently return +Success+ or +Failure+ results.
@@ -97,6 +99,43 @@ module Loqate
97
99
  def Failure(value, code: nil)
98
100
  Failure.new(value: value, code: code)
99
101
  end
102
+
103
+ # Unwraps a Result object. Returns the unwrapped value if the result is successful or raise
104
+ # an exception otherwise.
105
+ #
106
+ # @example When the given block returns a success
107
+ # class Action
108
+ # include Loqate::Result::Mixin
109
+ #
110
+ # def call
111
+ # Success('the value')
112
+ # end
113
+ # end
114
+ #
115
+ # operation.unwrap_result_or_raise { call } # => 'the value'
116
+ #
117
+ # @example When the given block returns a failure
118
+ # class Action
119
+ # include Loqate::Result::Mixin
120
+ #
121
+ # def call
122
+ # Failure(StandardError.new)
123
+ # end
124
+ # end
125
+ #
126
+ # operation.unwrap_result_or_raise { call } # => raises StandardError
127
+ #
128
+ # @raise [Object] If the result is not a success.
129
+ #
130
+ # @return [Object] The unwrapped object.
131
+ #
132
+ def unwrap_result_or_raise
133
+ result = yield
134
+
135
+ raise result.error if result.failure?
136
+
137
+ result.value
138
+ end
100
139
  end
101
140
  end
102
141
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Loqate
4
- VERSION = '0.2.0'
4
+ VERSION = '0.3.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: loqate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wilson Silva
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-10-31 00:00:00.000000000 Z
11
+ date: 2018-11-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: http