restful_resource 2.3.0 → 2.4.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.
- checksums.yaml +4 -4
- data/.circleci/config.yml +20 -0
- data/.codeclimate.yml +3 -0
- data/.rubocop.yml +5 -0
- data/.rubocop_todo.yml +203 -0
- data/CHANGELOG.md +5 -0
- data/README.md +1 -1
- data/Rakefile +5 -5
- data/lib/restful_resource/associations.rb +10 -8
- data/lib/restful_resource/base.rb +36 -33
- data/lib/restful_resource/http_client.rb +50 -48
- data/lib/restful_resource/instrumentation.rb +17 -20
- data/lib/restful_resource/null_logger.rb +1 -2
- data/lib/restful_resource/open_object.rb +2 -2
- data/lib/restful_resource/paginated_array.rb +3 -1
- data/lib/restful_resource/rails_validations.rb +12 -12
- data/lib/restful_resource/redirections.rb +5 -6
- data/lib/restful_resource/request.rb +0 -1
- data/lib/restful_resource/resource_id_missing_error.rb +1 -1
- data/lib/restful_resource/response.rb +4 -2
- data/lib/restful_resource/version.rb +1 -1
- data/restful_resource.gemspec +26 -25
- data/spec/fixtures.rb +7 -7
- data/spec/restful_resource/associations_spec.rb +23 -21
- data/spec/restful_resource/base_authorization_spec.rb +6 -7
- data/spec/restful_resource/base_spec.rb +134 -117
- data/spec/restful_resource/http_client_configuration_spec.rb +20 -19
- data/spec/restful_resource/http_client_spec.rb +38 -38
- data/spec/restful_resource/open_object_spec.rb +8 -8
- data/spec/restful_resource/rails_validations_spec.rb +68 -68
- data/spec/restful_resource/redirections_spec.rb +26 -26
- data/spec/spec_helper.rb +3 -4
- metadata +44 -13
- data/circle.yml +0 -3
@@ -1,5 +1,5 @@
|
|
1
1
|
# Use the Faraday-Typhoeus adapter provided by Typhoeus, not Faraday
|
2
|
-
require
|
2
|
+
require 'typhoeus/adapters/faraday'
|
3
3
|
|
4
4
|
module RestfulResource
|
5
5
|
class HttpClient
|
@@ -7,15 +7,16 @@ module RestfulResource
|
|
7
7
|
attr_reader :request, :response
|
8
8
|
|
9
9
|
def initialize(request, response = nil)
|
10
|
-
@request
|
10
|
+
@request = request
|
11
|
+
@response = assign_response(response)
|
11
12
|
end
|
12
13
|
|
13
14
|
def assign_response(response = nil)
|
14
|
-
if response
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
@response = if response
|
16
|
+
Response.new(body: response[:body], headers: response[:headers], status: response[:status])
|
17
|
+
else
|
18
|
+
Response.new
|
19
|
+
end
|
19
20
|
end
|
20
21
|
end
|
21
22
|
|
@@ -24,7 +25,7 @@ module RestfulResource
|
|
24
25
|
|
25
26
|
class ResourceNotFound < HttpError
|
26
27
|
def message
|
27
|
-
|
28
|
+
'HTTP 404: Resource Not Found'
|
28
29
|
end
|
29
30
|
end
|
30
31
|
|
@@ -40,44 +41,45 @@ module RestfulResource
|
|
40
41
|
|
41
42
|
class BadGateway < RetryableError
|
42
43
|
def message
|
43
|
-
|
44
|
+
'HTTP 502: Bad gateway'
|
44
45
|
end
|
45
46
|
end
|
46
47
|
|
47
48
|
class ServiceUnavailable < RetryableError
|
48
49
|
def message
|
49
|
-
|
50
|
+
'HTTP 503: Service unavailable'
|
50
51
|
end
|
51
52
|
end
|
52
53
|
|
53
54
|
class Timeout < RetryableError
|
54
55
|
def message
|
55
|
-
|
56
|
+
'Timeout: Service not responding'
|
56
57
|
end
|
57
58
|
end
|
58
59
|
|
59
60
|
class TooManyRequests < RetryableError
|
60
61
|
def message
|
61
|
-
|
62
|
+
'HTTP 429: Too Many Requests'
|
62
63
|
end
|
63
64
|
end
|
64
65
|
|
65
66
|
class ClientError < RetryableError
|
66
67
|
def message
|
67
|
-
|
68
|
+
'There was some client error'
|
68
69
|
end
|
69
70
|
end
|
70
71
|
|
71
72
|
def initialize(username: nil,
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
73
|
+
password: nil,
|
74
|
+
auth_token: nil,
|
75
|
+
logger: nil,
|
76
|
+
cache_store: nil,
|
77
|
+
connection: nil,
|
78
|
+
instrumentation: {},
|
79
|
+
open_timeout: 2,
|
80
|
+
timeout: 10,
|
81
|
+
faraday_config: nil,
|
82
|
+
faraday_options: nil)
|
81
83
|
api_name = instrumentation[:api_name] ||= 'api'
|
82
84
|
instrumentation[:request_instrument_name] ||= "http.#{api_name}"
|
83
85
|
instrumentation[:cache_instrument_name] ||= "http_cache.#{api_name}"
|
@@ -85,11 +87,13 @@ module RestfulResource
|
|
85
87
|
|
86
88
|
if instrumentation[:metric_class]
|
87
89
|
@metrics = Instrumentation.new(instrumentation.slice(:app_name,
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
90
|
+
:api_name,
|
91
|
+
:request_instrument_name,
|
92
|
+
:cache_instrument_name,
|
93
|
+
:server_cache_instrument_name,
|
94
|
+
:metric_class
|
95
|
+
)
|
96
|
+
)
|
93
97
|
@metrics.subscribe_to_notifications
|
94
98
|
end
|
95
99
|
|
@@ -100,7 +104,9 @@ module RestfulResource
|
|
100
104
|
request_instrument_name: instrumentation.fetch(:request_instrument_name, nil),
|
101
105
|
cache_instrument_name: instrumentation.fetch(:cache_instrument_name, nil),
|
102
106
|
server_cache_instrument_name: instrumentation.fetch(:server_cache_instrument_name, nil),
|
103
|
-
faraday_config: faraday_config
|
107
|
+
faraday_config: faraday_config,
|
108
|
+
faraday_options: faraday_options
|
109
|
+
)
|
104
110
|
|
105
111
|
if auth_token
|
106
112
|
@connection.headers[:authorization] = "Bearer #{auth_token}"
|
@@ -168,20 +174,19 @@ module RestfulResource
|
|
168
174
|
attr_reader :default_open_timeout, :default_timeout
|
169
175
|
|
170
176
|
def initialize_connection(logger: nil,
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
177
|
+
cache_store: nil,
|
178
|
+
instrumenter: nil,
|
179
|
+
request_instrument_name: nil,
|
180
|
+
cache_instrument_name: nil,
|
181
|
+
server_cache_instrument_name: nil,
|
182
|
+
faraday_config: nil,
|
183
|
+
faraday_options: nil)
|
184
|
+
|
185
|
+
@connection = Faraday.new(nil, faraday_options) do |b|
|
179
186
|
b.request :json
|
180
187
|
b.response :raise_error
|
181
188
|
|
182
|
-
if logger
|
183
|
-
b.response :logger, logger
|
184
|
-
end
|
189
|
+
b.response :logger, logger if logger
|
185
190
|
|
186
191
|
if server_cache_instrument_name
|
187
192
|
b.use :cdn_metrics, instrumenter: instrumenter,
|
@@ -195,13 +200,9 @@ module RestfulResource
|
|
195
200
|
instrument_name: cache_instrument_name
|
196
201
|
end
|
197
202
|
|
198
|
-
if instrumenter && request_instrument_name
|
199
|
-
b.use :instrumentation, name: request_instrument_name
|
200
|
-
end
|
203
|
+
b.use :instrumentation, name: request_instrument_name if instrumenter && request_instrument_name
|
201
204
|
|
202
|
-
|
203
|
-
faraday_config.call(b)
|
204
|
-
end
|
205
|
+
faraday_config&.call(b)
|
205
206
|
|
206
207
|
b.response :encoding
|
207
208
|
b.use :gzip
|
@@ -211,7 +212,7 @@ module RestfulResource
|
|
211
212
|
end
|
212
213
|
|
213
214
|
def build_user_agent(app_name)
|
214
|
-
parts = [
|
215
|
+
parts = ['carwow/internal']
|
215
216
|
parts << "RestfulResource/#{VERSION}"
|
216
217
|
parts << "(#{app_name})" if app_name
|
217
218
|
parts << "Faraday/#{Faraday::VERSION}"
|
@@ -232,10 +233,11 @@ module RestfulResource
|
|
232
233
|
rescue Faraday::ConnectionFailed
|
233
234
|
raise
|
234
235
|
rescue Faraday::TimeoutError
|
235
|
-
raise HttpClient::Timeout
|
236
|
+
raise HttpClient::Timeout, request
|
236
237
|
rescue Faraday::ClientError => e
|
237
238
|
response = e.response
|
238
|
-
raise ClientError
|
239
|
+
raise ClientError, request unless response
|
240
|
+
|
239
241
|
case response[:status]
|
240
242
|
when 404 then raise HttpClient::ResourceNotFound.new(request, response)
|
241
243
|
when 409 then raise HttpClient::Conflict.new(request, response)
|
@@ -2,7 +2,6 @@ require 'active_support/notifications'
|
|
2
2
|
|
3
3
|
module RestfulResource
|
4
4
|
class Instrumentation
|
5
|
-
|
6
5
|
def initialize(app_name:, api_name:, request_instrument_name:, cache_instrument_name:, server_cache_instrument_name:, metric_class:)
|
7
6
|
@app_name = app_name
|
8
7
|
@api_name = api_name
|
@@ -50,18 +49,18 @@ module RestfulResource
|
|
50
49
|
# count#quotes_site.research_site_api.cache_hit=1
|
51
50
|
# count#quotes_site.research_site_api.api_v2_cap_derivatives.cache_hit=1
|
52
51
|
case cache_status
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
52
|
+
when :fresh, :valid
|
53
|
+
metric_class.count cache_notifier_namespace(metric: 'cache_hit'), 1
|
54
|
+
metric_class.count cache_notifier_namespace(metric: 'cache_hit', event: event), 1
|
55
|
+
when :invalid, :miss
|
56
|
+
metric_class.count cache_notifier_namespace(metric: 'cache_miss'), 1
|
57
|
+
metric_class.count cache_notifier_namespace(metric: 'cache_miss', event: event), 1
|
58
|
+
when :unacceptable
|
59
|
+
metric_class.count cache_notifier_namespace(metric: 'cache_not_cacheable'), 1
|
60
|
+
metric_class.count cache_notifier_namespace(metric: 'cache_not_cacheable', event: event), 1
|
61
|
+
when :bypass
|
62
|
+
metric_class.count cache_notifier_namespace(metric: 'cache_bypass'), 1
|
63
|
+
metric_class.count cache_notifier_namespace(metric: 'cache_bypass', event: event), 1
|
65
64
|
end
|
66
65
|
end
|
67
66
|
|
@@ -71,7 +70,7 @@ module RestfulResource
|
|
71
70
|
client_cache_status = event.payload.fetch(:client_cache_status, nil)
|
72
71
|
server_cache_status = event.payload.fetch(:server_cache_status, nil)
|
73
72
|
|
74
|
-
if client_cache_status.nil? || !client_cache_status.in?([
|
73
|
+
if client_cache_status.nil? || !client_cache_status.in?(%i[fresh valid])
|
75
74
|
# Outputs log lines like:
|
76
75
|
# count#quotes_site.research_site_api.server_cache_hit=1
|
77
76
|
# count#quotes_site.research_site_api.api_v2_cap_derivatives.server_cache_hit=1
|
@@ -100,19 +99,17 @@ module RestfulResource
|
|
100
99
|
end
|
101
100
|
|
102
101
|
def validate_metric_class!
|
103
|
-
metric_methods = %i
|
104
|
-
if metric_methods.any? {|m| !metric_class.respond_to?(m) }
|
105
|
-
raise ArgumentError.new "Metric class '#{metric_class}' does not respond to #{metric_methods.join ','}"
|
106
|
-
end
|
102
|
+
metric_methods = %i[count sample measure]
|
103
|
+
raise ArgumentError, "Metric class '#{metric_class}' does not respond to #{metric_methods.join ','}" if metric_methods.any? { |m| !metric_class.respond_to?(m) }
|
107
104
|
end
|
108
105
|
|
109
106
|
def cache_notifier_namespace(metric:, event: nil)
|
110
107
|
[app_name, api_name, base_request_path(event), metric].compact.join('.')
|
111
108
|
end
|
112
109
|
|
113
|
-
#
|
110
|
+
# Converts a path like "/api/v2/cap_derivatives/75423/with_colours" to "api_v2_cap_derivatives_with_colours"
|
114
111
|
def base_request_path(event)
|
115
|
-
path_from_event(event).split('/').drop(1).select {|a| a.match(/\d+/).nil? }.join('_') if event
|
112
|
+
path_from_event(event).split('/').drop(1).select { |a| a.match(/\d+/).nil? }.join('_') if event
|
116
113
|
end
|
117
114
|
|
118
115
|
def path_from_event(event)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module RestfulResource
|
2
2
|
class OpenObject
|
3
|
-
def initialize(attributes = {},
|
3
|
+
def initialize(attributes = {}, _hack_for_activeresource = false)
|
4
4
|
@inner_object = OpenStruct.new(attributes)
|
5
5
|
end
|
6
6
|
|
@@ -16,7 +16,7 @@ module RestfulResource
|
|
16
16
|
super || @inner_object.respond_to?(method, include_private)
|
17
17
|
end
|
18
18
|
|
19
|
-
def as_json(options=nil)
|
19
|
+
def as_json(options = nil)
|
20
20
|
@inner_object.send(:table).as_json(options)
|
21
21
|
end
|
22
22
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module RestfulResource
|
2
2
|
class PaginatedArray < Array
|
3
|
-
def initialize(original_array, previous_page_url:, next_page_url:, total_count:
|
3
|
+
def initialize(original_array, previous_page_url:, next_page_url:, total_count:)
|
4
4
|
super(original_array)
|
5
5
|
|
6
6
|
@previous_page_url = previous_page_url
|
@@ -21,8 +21,10 @@ module RestfulResource
|
|
21
21
|
end
|
22
22
|
|
23
23
|
private
|
24
|
+
|
24
25
|
def get_page_from_url(url)
|
25
26
|
return nil unless url
|
27
|
+
|
26
28
|
params = Rack::Utils.parse_query URI(url).query
|
27
29
|
params['page'].to_i
|
28
30
|
end
|
@@ -6,13 +6,13 @@ module RestfulResource
|
|
6
6
|
rescue HttpClient::UnprocessableEntity => e
|
7
7
|
errors = parse_json(e.response.body)
|
8
8
|
result = nil
|
9
|
-
if errors.is_a?(Hash) && errors.
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
9
|
+
result = if errors.is_a?(Hash) && errors.key?('errors')
|
10
|
+
data.merge(errors)
|
11
|
+
else
|
12
|
+
data.merge(errors: errors)
|
13
|
+
end
|
14
14
|
result = result.merge(id: id)
|
15
|
-
|
15
|
+
new(result)
|
16
16
|
end
|
17
17
|
|
18
18
|
def post(data: {}, **)
|
@@ -30,12 +30,12 @@ module RestfulResource
|
|
30
30
|
rescue HttpClient::UnprocessableEntity => e
|
31
31
|
errors = parse_json(e.response.body)
|
32
32
|
result = nil
|
33
|
-
if errors.is_a?(Hash) && errors.
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
33
|
+
result = if errors.is_a?(Hash) && errors.key?('errors')
|
34
|
+
data.merge(errors)
|
35
|
+
else
|
36
|
+
data.merge(errors: errors)
|
37
|
+
end
|
38
|
+
new(result)
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module RestfulResource
|
2
2
|
class MaximumAttemptsReached < StandardError
|
3
3
|
def message
|
4
|
-
|
4
|
+
'The maximum attempts limit was reached before the resource was ready'
|
5
5
|
end
|
6
6
|
end
|
7
7
|
|
@@ -11,12 +11,13 @@ module RestfulResource
|
|
11
11
|
def post(data: {}, delay: 1.0, max_attempts: 10, headers: {}, open_timeout: nil, timeout: nil, **params)
|
12
12
|
url = collection_url(params)
|
13
13
|
|
14
|
-
response =
|
14
|
+
response = accept_redirected_result(response: http.post(url, data: data, headers: headers, open_timeout: nil, timeout: nil), delay: delay, max_attempts: max_attempts)
|
15
15
|
|
16
|
-
|
16
|
+
new(parse_json(response.body))
|
17
17
|
end
|
18
18
|
|
19
19
|
private
|
20
|
+
|
20
21
|
def self.accept_redirected_result(response:, delay:, max_attempts:)
|
21
22
|
new_response = response
|
22
23
|
if response.status == 303
|
@@ -32,9 +33,7 @@ module RestfulResource
|
|
32
33
|
new_response = http.get(resource_location, headers: {}, open_timeout: nil, timeout: nil)
|
33
34
|
end
|
34
35
|
|
35
|
-
if attempts == max_attempts
|
36
|
-
raise RestfulResource::MaximumAttemptsReached
|
37
|
-
end
|
36
|
+
raise RestfulResource::MaximumAttemptsReached if attempts == max_attempts
|
38
37
|
end
|
39
38
|
response = new_response
|
40
39
|
end
|
@@ -2,8 +2,10 @@ module RestfulResource
|
|
2
2
|
class Response
|
3
3
|
attr_reader :body, :headers, :status
|
4
4
|
|
5
|
-
def initialize(body:
|
6
|
-
@body
|
5
|
+
def initialize(body: '{}', headers: {}, status: nil)
|
6
|
+
@body = body
|
7
|
+
@headers = headers
|
8
|
+
@status = status
|
7
9
|
end
|
8
10
|
end
|
9
11
|
end
|
data/restful_resource.gemspec
CHANGED
@@ -1,36 +1,37 @@
|
|
1
|
-
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
3
|
require 'restful_resource/version'
|
5
4
|
|
6
5
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
6
|
+
spec.name = 'restful_resource'
|
8
7
|
spec.version = RestfulResource::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
11
|
-
spec.description =
|
12
|
-
spec.summary =
|
13
|
-
spec.homepage =
|
14
|
-
spec.license =
|
8
|
+
spec.authors = ['David Santoro', 'Federico Rebora']
|
9
|
+
spec.email = ['developers@carwow.co.uk']
|
10
|
+
spec.description = 'A simple activerecord inspired rest resource base class implemented using rest-client'
|
11
|
+
spec.summary = 'A simple activerecord inspired rest resource base class implemented using rest-client'
|
12
|
+
spec.homepage = 'http://www.github.com/carwow/restful_resource'
|
13
|
+
spec.license = 'MIT'
|
15
14
|
|
16
|
-
spec.files = `git ls-files`.split(
|
15
|
+
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
17
16
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
17
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
-
spec.require_paths = [
|
20
|
-
spec.required_ruby_version = '>= 2.
|
18
|
+
spec.require_paths = ['lib']
|
19
|
+
spec.required_ruby_version = '>= 2.4'
|
21
20
|
|
22
|
-
spec.add_development_dependency
|
23
|
-
spec.add_development_dependency
|
24
|
-
spec.add_development_dependency
|
25
|
-
spec.add_development_dependency
|
21
|
+
spec.add_development_dependency 'bundler', '~> 1.3'
|
22
|
+
spec.add_development_dependency 'carwow_rubocop', '~> 2.0'
|
23
|
+
spec.add_development_dependency 'rake'
|
24
|
+
spec.add_development_dependency 'rspec', '~> 3.1'
|
25
|
+
spec.add_development_dependency 'rspec_junit_formatter'
|
26
|
+
spec.add_development_dependency 'rspec-its'
|
26
27
|
|
27
|
-
spec.add_dependency
|
28
|
-
spec.add_dependency
|
29
|
-
spec.add_dependency
|
30
|
-
spec.add_dependency
|
31
|
-
spec.add_dependency
|
32
|
-
spec.add_dependency
|
33
|
-
spec.add_dependency
|
34
|
-
spec.add_dependency
|
35
|
-
spec.add_dependency
|
28
|
+
spec.add_dependency 'activesupport'
|
29
|
+
spec.add_dependency 'faraday'
|
30
|
+
spec.add_dependency 'faraday-cdn-metrics'
|
31
|
+
spec.add_dependency 'faraday-encoding'
|
32
|
+
spec.add_dependency 'faraday-http-cache'
|
33
|
+
spec.add_dependency 'faraday_middleware'
|
34
|
+
spec.add_dependency 'link_header'
|
35
|
+
spec.add_dependency 'rack'
|
36
|
+
spec.add_dependency 'typhoeus'
|
36
37
|
end
|
data/spec/fixtures.rb
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
class Make < RestfulResource::Base
|
2
|
-
resource_path
|
2
|
+
resource_path 'makes'
|
3
3
|
has_many :models
|
4
4
|
end
|
5
5
|
|
6
6
|
class Model < RestfulResource::Base
|
7
7
|
has_one :make
|
8
|
-
resource_path
|
8
|
+
resource_path 'groups/:group_id/makes/:make_slug/models'
|
9
9
|
end
|
10
10
|
|
11
11
|
class Dealer < RestfulResource::Base
|
12
12
|
include RestfulResource::RailsValidations
|
13
13
|
|
14
|
-
resource_path
|
14
|
+
resource_path 'dealers'
|
15
15
|
end
|
16
16
|
|
17
17
|
class BaseA < RestfulResource::Base
|
@@ -21,11 +21,11 @@ class BaseB < RestfulResource::Base
|
|
21
21
|
end
|
22
22
|
|
23
23
|
class TestA < BaseA
|
24
|
-
|
24
|
+
resource_path 'testa'
|
25
25
|
end
|
26
26
|
|
27
27
|
class TestB < BaseB
|
28
|
-
|
28
|
+
resource_path 'testb'
|
29
29
|
end
|
30
30
|
|
31
31
|
class ModelWithRedirections < RestfulResource::Base
|
@@ -36,7 +36,7 @@ end
|
|
36
36
|
|
37
37
|
module ComplicatedModule
|
38
38
|
class Parent < BaseA
|
39
|
-
resource_path
|
39
|
+
resource_path 'parent'
|
40
40
|
has_many :children
|
41
41
|
has_many :other_things
|
42
42
|
has_many :missing
|
@@ -51,7 +51,7 @@ module ComplicatedModule
|
|
51
51
|
has_one :parent
|
52
52
|
|
53
53
|
def full_name
|
54
|
-
"#{
|
54
|
+
"#{first_name} #{second_name}"
|
55
55
|
end
|
56
56
|
end
|
57
57
|
end
|
@@ -1,53 +1,55 @@
|
|
1
1
|
require_relative '../spec_helper'
|
2
2
|
|
3
3
|
describe RestfulResource::Associations do
|
4
|
-
describe
|
5
|
-
before
|
6
|
-
@parent = ComplicatedModule::Parent.new(
|
4
|
+
describe '#has_many' do
|
5
|
+
before do
|
6
|
+
@parent = ComplicatedModule::Parent.new(
|
7
7
|
name: 'John Doe',
|
8
|
-
other_things: [{stuff: 'aaa'}, {stuff: 'bbb'}],
|
8
|
+
other_things: [{ stuff: 'aaa' }, { stuff: 'bbb' }],
|
9
9
|
children:
|
10
10
|
[
|
11
|
-
{first_name: 'David', second_name: 'Doe'},
|
12
|
-
{first_name: 'Mary', second_name: 'Doe'}
|
11
|
+
{ first_name: 'David', second_name: 'Doe' },
|
12
|
+
{ first_name: 'Mary', second_name: 'Doe' }
|
13
13
|
]
|
14
|
-
|
14
|
+
|
15
|
+
)
|
15
16
|
end
|
16
17
|
|
17
|
-
it
|
18
|
+
it 'adds a method to access nested resource' do
|
18
19
|
expect(@parent.children.first.first_name).to eq 'David'
|
19
20
|
expect(@parent.children.last.first_name).to eq 'Mary'
|
20
|
-
expect(@parent.children.first.to_json).to eq({first_name: 'David', second_name: 'Doe'}.to_json)
|
21
|
+
expect(@parent.children.first.to_json).to eq({ first_name: 'David', second_name: 'Doe' }.to_json)
|
21
22
|
end
|
22
23
|
|
23
|
-
it
|
24
|
+
it 'picks the right class for the instantiation of chilren' do
|
24
25
|
expect(@parent.children.first.full_name).to eq 'David Doe'
|
25
26
|
end
|
26
27
|
|
27
|
-
it "
|
28
|
+
it "uses open object when can't infer class name of association" do
|
28
29
|
expect(@parent.other_things.first.stuff).to eq 'aaa'
|
29
30
|
end
|
30
31
|
|
31
|
-
it
|
32
|
+
it 'returns nil for missing associations' do
|
32
33
|
expect(@parent.missing).to be_nil
|
33
34
|
end
|
34
35
|
end
|
35
36
|
|
36
|
-
describe
|
37
|
-
before
|
38
|
-
@child = ComplicatedModule::Child.new(
|
37
|
+
describe '#has_one' do
|
38
|
+
before do
|
39
|
+
@child = ComplicatedModule::Child.new(
|
39
40
|
first_name: 'David', second_name: 'Smith',
|
40
|
-
parent: {name: 'John Smith'}
|
41
|
-
|
41
|
+
parent: { name: 'John Smith' }
|
42
|
+
|
43
|
+
)
|
42
44
|
end
|
43
45
|
|
44
|
-
it
|
46
|
+
it 'adds a method to access nested resource' do
|
45
47
|
expect(@child.parent.name).to eq 'John Smith'
|
46
|
-
expect(@child.parent.to_json).to eq({name: 'John Smith'}.to_json)
|
48
|
+
expect(@child.parent.to_json).to eq({ name: 'John Smith' }.to_json)
|
47
49
|
end
|
48
50
|
|
49
|
-
it
|
50
|
-
expect(@child.parent
|
51
|
+
it 'picks the right class for the instantiation of chilren' do
|
52
|
+
expect(@child.parent).to be_is_parent
|
51
53
|
end
|
52
54
|
end
|
53
55
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require_relative '../spec_helper'
|
2
2
|
|
3
3
|
describe RestfulResource::Base, 'authorization' do
|
4
|
-
before
|
4
|
+
before do
|
5
5
|
class FirstClient < RestfulResource::Base
|
6
6
|
end
|
7
7
|
|
@@ -21,20 +21,19 @@ describe RestfulResource::Base, 'authorization' do
|
|
21
21
|
FirstClient.configure(base_url: 'http://api.carwow.co.uk/api/first')
|
22
22
|
SecondClient.configure(base_url: 'http://api.carwow.co.uk/api/second',
|
23
23
|
username: 'test_user',
|
24
|
-
password: 'test_pass'
|
24
|
+
password: 'test_pass'
|
25
|
+
)
|
25
26
|
end
|
26
27
|
|
27
|
-
it
|
28
|
+
it 'uses two different http instances' do
|
28
29
|
expect(FirstTest.send(:http)).not_to equal(SecondTest.send(:http))
|
29
30
|
end
|
30
31
|
|
31
|
-
it '
|
32
|
+
it 'has same http auth on superclass' do
|
32
33
|
expect(SecondTest.send(:http)).to equal(SecondClient.send(:http))
|
33
34
|
end
|
34
35
|
|
35
|
-
it '
|
36
|
+
it 'raises exception if base_url is not set' do
|
36
37
|
expect { NotConfiguredClient.send(:base_url) }.to raise_error 'Base url missing'
|
37
38
|
end
|
38
|
-
|
39
39
|
end
|
40
|
-
|