api_recipes 2.6.1 → 2.8.1

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: e8a4b8c1642a323a4a72f8303de3fbe408d15fab5a5f127fb5c2ad3fcb0f543a
4
- data.tar.gz: 2f24944c94c92e02224629c25a9c1da052c902d86abb8649d7faeb02e2111046
3
+ metadata.gz: c9d0a5a4530af3af22b9b22c091002d316e1bf7065c612d1d74f18f3aa62e37d
4
+ data.tar.gz: 5d322a843fa2db9cceb97cd9733b482ce17626342ad519ea036c0c821efe0d8b
5
5
  SHA512:
6
- metadata.gz: 445c2a2154979454088bb64e32c3e648d5cc779a184d6ae9079fed286913e66d7fec703d41d2de15f268aa386bc174230ce7ed2b5e5fa20a8bb2d9d8b16d92c0
7
- data.tar.gz: d22528bfcf3acbb9a0ebd8e3aa3826eb52985f3a081a1b71abcf29291d8958922c6a76be302b1fcad6fc45b1ca614008812050793ca19d6dec9400c73db390a9
6
+ metadata.gz: 6ee0d8d0c2e4c52aafa513c8619f92c1ec6b5425cf06911fc48d8d18562855cd4d0aabe96bf68985323663bdb4cb461e56b353c06431e2430a3ef9d51ecd6021
7
+ data.tar.gz: 4ef8593a855dd30fd21ee97642dcc5d832f7ec34218393131d1fe6758af1dbe4a8e5ad8d76f3612d289ef6e85d02a7640a65490f6b7dc103d0e32f43fbed2409
data/lib/api_recipes.rb CHANGED
@@ -32,13 +32,13 @@ module ApiRecipes
32
32
 
33
33
  define_method api_name do
34
34
  configs = ApiRecipes._aprcps_merge_apis_configs(api_name, configs.deep_symbolize_keys)
35
- api = Api.new(api_name, configs)
35
+ api = Api.new(api_name, configs, self)
36
36
  ApiRecipes.copy_global_authorizations_to_api api
37
37
  api
38
38
  end
39
39
  define_singleton_method api_name do
40
40
  configs = ApiRecipes._aprcps_merge_apis_configs(api_name, configs.deep_symbolize_keys)
41
- api = Api.new(api_name, configs)
41
+ api = Api.new(api_name, configs, self)
42
42
  ApiRecipes.copy_global_authorizations_to_api api
43
43
  api
44
44
  end
@@ -58,6 +58,7 @@ module ApiRecipes
58
58
  unless @configuration
59
59
  @configuration = Configuration.new
60
60
  end
61
+
61
62
  @configuration
62
63
  end
63
64
 
@@ -105,7 +106,7 @@ module ApiRecipes
105
106
  def self._aprcps_define_global_apis
106
107
  configuration.apis_configs.each do |api_name, api_configs|
107
108
  api_name = api_name.to_sym
108
- _aprcps_global_storage[api_name] = Api.new api_name, api_configs
109
+ _aprcps_global_storage[api_name] = Api.new api_name, api_configs, self
109
110
  define_singleton_method api_name do
110
111
  _aprcps_global_storage[api_name]
111
112
  end
@@ -116,6 +117,7 @@ module ApiRecipes
116
117
  unless @storage
117
118
  @storage = {}
118
119
  end
120
+
119
121
  @storage
120
122
  end
121
123
 
@@ -130,11 +132,9 @@ module ApiRecipes
130
132
  unless api_name.is_a?(String) || api_name.is_a?(Symbol)
131
133
  raise ArgumentError, "no api_name provided. Given: #{api_name.inspect}"
132
134
  end
133
- unless ApiRecipes.configuration.apis_configs[api_name]
134
- ApiRecipes.configuration.apis_configs[api_name] = {}
135
- end
135
+ global_api_configs = _aprcps_global_storage[api_name]&.configs || {}
136
136
  if configs
137
- ApiRecipes.configuration.apis_configs[api_name].merge(configs) do |_, old_val, new_val|
137
+ global_api_configs.deep_merge(configs) do |_, old_val, new_val|
138
138
  if new_val.nil?
139
139
  old_val
140
140
  else
@@ -142,7 +142,7 @@ module ApiRecipes
142
142
  end
143
143
  end
144
144
  else
145
- ApiRecipes.configuration.apis_configs[api_name]
145
+ global_api_configs
146
146
  end
147
147
  end
148
148
  end
@@ -2,13 +2,14 @@ module ApiRecipes
2
2
  class Api
3
3
 
4
4
  attr_accessor :name, :configs, :authorization, :basic_auth
5
- attr_reader :base_configs
5
+ attr_reader :base_configs, :object
6
6
 
7
- BASE_CONFIGS_KEYS = [:protocol, :host, :port, :api_version, :timeout, :on_bad_code]
7
+ BASE_CONFIGS_KEYS = [:protocol, :host, :port, :api_version, :timeout, :on_bad_code, :verify_with]
8
8
 
9
- def initialize(name, configs)
9
+ def initialize(name, configs, object)
10
10
  @name = name
11
11
  @configs = ApiRecipes::Settings::DEFAULT.merge configs
12
+ @object = object
12
13
 
13
14
  # Generate some_api.some_endpoint methods
14
15
  # e.g. github.users
@@ -3,6 +3,8 @@ module ApiRecipes
3
3
 
4
4
  attr_reader :api, :name, :params, :route, :children
5
5
 
6
+ FORWARDABLE_PARAMS = %i[verify_with].freeze
7
+
6
8
  def initialize(api: nil, name: nil, path: nil, params: {}, request_params: [], &block)
7
9
  @api = api
8
10
  @name = name
@@ -52,6 +54,8 @@ module ApiRecipes
52
54
  # puts "generating children of #{@name}: #{children.inspect}"
53
55
  if children
54
56
  children.each do |ep_name, pars|
57
+ pars = forwardable_params.merge(pars) if pars
58
+ # TODO: Merge pars with params
55
59
  # puts "Creating Endpoint '#{@name}' child '#{ep_name}' passing path #{build_path}"
56
60
  define_singleton_method ep_name do |*request_params, &block|
57
61
  Endpoint.new api: @api, name: ep_name, path: build_path, params: pars, request_params: request_params, &block
@@ -89,7 +93,6 @@ module ApiRecipes
89
93
  end
90
94
  # Merge DEFAULT_ROUTE_ATTRIBUTES with Api base_configs
91
95
  # Then merge the result with provided attributes
92
-
93
96
  @params = Settings::DEFAULT_ROUTE_ATTRIBUTES.inject({}) do |out, key_val|
94
97
  new_val = @api.base_configs[key_val.first]
95
98
  out[key_val.first] = new_val.nil? ? key_val.last : new_val
@@ -126,5 +129,9 @@ module ApiRecipes
126
129
  def required_params_for_path
127
130
  absolute_path.scan(/:(\w+)/).flatten.map { |p| p.to_sym }
128
131
  end
132
+
133
+ def forwardable_params
134
+ params.select { |k, v| FORWARDABLE_PARAMS.include? k }
135
+ end
129
136
  end
130
137
  end
@@ -40,8 +40,16 @@ module ApiRecipes
40
40
  end
41
41
 
42
42
  class ResponseCodeNotAsExpected < Exception
43
- def initialize(path, expected_code = nil, response_code = nil, response_body = nil)
44
- message = "response code for request on route '#{path}' has returned #{response_code}, but #{expected_code} was expected\n\nResponse body:\n #{response_body}"
43
+
44
+ attr_reader :path, :expected_code, :response
45
+
46
+ def initialize(path, expected_code = nil, response = nil, message: nil)
47
+ @path = path
48
+ @expected_code = expected_code
49
+ @response = response
50
+ unless message
51
+ message = "response code for request on route '#{@path}' has returned '#{@response.code}', but '#{@expected_code}' was expected\n\nResponse body:\n #{@response.body}"
52
+ end
45
53
  super(message)
46
54
  end
47
55
  end
@@ -11,6 +11,7 @@ module ApiRecipes
11
11
  def data
12
12
  return @data unless @data.nil?
13
13
 
14
+ # TODO: rescue nil?
14
15
  @data = @original_response.parse
15
16
  end
16
17
 
@@ -43,31 +43,40 @@ module ApiRecipes
43
43
 
44
44
  def build_url_from_path
45
45
  attrs = {
46
- scheme: settings[:protocol],
46
+ scheme: settings[:protocol].to_s,
47
47
  host: settings[:host],
48
48
  port: port,
49
- path: URI.escape(path)
49
+ path: path
50
50
  }
51
- URI::Generic.build attrs
51
+ URI::Generic.build2 attrs
52
52
  end
53
53
 
54
54
  def check_response_code
55
- # If :ok_code property is present, check the response code
56
55
  ok_code = false
57
56
  code = @response.code
58
- if expected_code = attributes[:ok_code]
59
- # If the code does not match, apply the requested strategy
60
- ok_code = true if code == expected_code
57
+ message = nil
58
+
59
+ verify_with = attributes[:verify_with]
60
+ if verify_with && @api.object.respond_to?(verify_with, true )
61
+ ok_code = @api.object.send verify_with, @response
62
+ message = "response for request on route '#{path}' was not valid. Verified with #{@api.object}##{verify_with}.\n\nResponse body:\n #{@response.body}"
61
63
  else
62
- # Default: 200 <= OK < 300
63
- ok_code = true if (code >= 200 && code < 300)
64
- expected_code = '200 <= CODE < 300'
64
+ # If :ok_code property is present, check the response code
65
+ if expected_code = attributes[:ok_code]
66
+ # If the code does not match, apply the requested strategy
67
+ ok_code = true if code == expected_code
68
+ else
69
+ # Default: 200 <= OK < 300
70
+ ok_code = true if @response.status.success?
71
+ expected_code = '200 <= CODE < 300'
72
+ end
65
73
  end
74
+
66
75
  unless ok_code
67
76
  case attributes[:on_bad_code].to_s
68
77
  when 'ignore'
69
78
  when 'raise'
70
- raise ResponseCodeNotAsExpected.new(path, expected_code, code, @response.body)
79
+ raise ResponseCodeNotAsExpected.new(path, expected_code, @response, message: message)
71
80
  end
72
81
  end
73
82
  end
@@ -81,12 +90,12 @@ module ApiRecipes
81
90
  end
82
91
 
83
92
  def port
84
- settings[:port] || case settings[:protocol]
85
- when 'http'
86
- 80
87
- when 'https'
88
- 443
89
- end
93
+ settings[:port].to_s || case settings[:protocol].to_s
94
+ when 'http'
95
+ '80'
96
+ when 'https'
97
+ '443'
98
+ end
90
99
  end
91
100
 
92
101
  def prepare_request
@@ -9,7 +9,8 @@ module ApiRecipes
9
9
  base_url: nil,
10
10
  timeout: 3,
11
11
  on_bad_code: 'raise',
12
- endpoints: {}
12
+ endpoints: {},
13
+ verify_with: nil
13
14
  }
14
15
 
15
16
  DEFAULT_ROUTE_ATTRIBUTES = {
@@ -18,7 +19,8 @@ module ApiRecipes
18
19
  path: nil,
19
20
  ok_code: nil,
20
21
  timeout: DEFAULT[:timeout],
21
- on_bad_code: DEFAULT[:on_bad_code]
22
+ on_bad_code: DEFAULT[:on_bad_code],
23
+ verify_with: DEFAULT[:verify_with]
22
24
  }
23
25
 
24
26
  AVAILABLE_PARAMS_ENCODINGS = %w(form params json body)
@@ -77,6 +77,37 @@ class Hash
77
77
  end
78
78
  end
79
79
 
80
+ # Returns a new hash with +self+ and +other_hash+ merged recursively.
81
+ #
82
+ # h1 = { a: true, b: { c: [1, 2, 3] } }
83
+ # h2 = { a: false, b: { x: [3, 4, 5] } }
84
+ #
85
+ # h1.deep_merge(h2) # => { a: false, b: { c: [1, 2, 3], x: [3, 4, 5] } }
86
+ #
87
+ # Like with Hash#merge in the standard library, a block can be provided
88
+ # to merge values:
89
+ #
90
+ # h1 = { a: 100, b: 200, c: { c1: 100 } }
91
+ # h2 = { b: 250, c: { c1: 200 } }
92
+ # h1.deep_merge(h2) { |key, this_val, other_val| this_val + other_val }
93
+ # # => { a: 100, b: 450, c: { c1: 300 } }
94
+ def deep_merge(other_hash, &block)
95
+ dup.deep_merge!(other_hash, &block)
96
+ end
97
+
98
+ # Same as +deep_merge+, but modifies +self+.
99
+ def deep_merge!(other_hash, &block)
100
+ merge!(other_hash) do |key, this_val, other_val|
101
+ if this_val.is_a?(Hash) && other_val.is_a?(Hash)
102
+ this_val.deep_merge(other_val, &block)
103
+ elsif block_given?
104
+ block.call(key, this_val, other_val)
105
+ else
106
+ other_val
107
+ end
108
+ end
109
+ end
110
+
80
111
  # Returns a new hash with all keys converted by the block operation.
81
112
  # This includes the keys from the root hash and from all
82
113
  # nested hashes and arrays.
@@ -1,3 +1,3 @@
1
1
  module ApiRecipes
2
- VERSION = '2.6.1'.freeze
2
+ VERSION = '2.8.1'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: api_recipes
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.6.1
4
+ version: 2.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alessandro Verlato
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-10-27 00:00:00.000000000 Z
11
+ date: 2021-02-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: http