haveapi 0.20.0 → 0.21.1

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.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/Rakefile +6 -6
  4. data/haveapi.gemspec +13 -13
  5. data/lib/haveapi/action.rb +153 -167
  6. data/lib/haveapi/action_state.rb +2 -6
  7. data/lib/haveapi/actions/default.rb +8 -10
  8. data/lib/haveapi/api.rb +2 -1
  9. data/lib/haveapi/authentication/base.rb +5 -8
  10. data/lib/haveapi/authentication/basic/provider.rb +4 -5
  11. data/lib/haveapi/authentication/chain.rb +19 -17
  12. data/lib/haveapi/authentication/oauth2/config.rb +12 -32
  13. data/lib/haveapi/authentication/oauth2/provider.rb +20 -30
  14. data/lib/haveapi/authentication/oauth2/revoke_endpoint.rb +1 -2
  15. data/lib/haveapi/authentication/token/action_config.rb +5 -3
  16. data/lib/haveapi/authentication/token/config.rb +5 -5
  17. data/lib/haveapi/authentication/token/provider.rb +33 -37
  18. data/lib/haveapi/authorization.rb +10 -4
  19. data/lib/haveapi/client_example.rb +11 -14
  20. data/lib/haveapi/client_examples/curl.rb +37 -37
  21. data/lib/haveapi/client_examples/fs_client.rb +29 -31
  22. data/lib/haveapi/client_examples/http.rb +35 -36
  23. data/lib/haveapi/client_examples/js_client.rb +62 -63
  24. data/lib/haveapi/client_examples/php_client.rb +77 -76
  25. data/lib/haveapi/client_examples/ruby_cli.rb +30 -30
  26. data/lib/haveapi/client_examples/ruby_client.rb +26 -26
  27. data/lib/haveapi/common.rb +3 -4
  28. data/lib/haveapi/context.rb +11 -10
  29. data/lib/haveapi/example.rb +9 -4
  30. data/lib/haveapi/example_list.rb +2 -2
  31. data/lib/haveapi/exceptions.rb +1 -1
  32. data/lib/haveapi/extensions/action_exceptions.rb +2 -2
  33. data/lib/haveapi/extensions/base.rb +1 -3
  34. data/lib/haveapi/extensions/exception_mailer.rb +260 -257
  35. data/lib/haveapi/hooks.rb +40 -39
  36. data/lib/haveapi/metadata.rb +1 -1
  37. data/lib/haveapi/model_adapter.rb +16 -27
  38. data/lib/haveapi/model_adapters/active_record.rb +59 -69
  39. data/lib/haveapi/output_formatter.rb +7 -7
  40. data/lib/haveapi/output_formatters/base.rb +2 -4
  41. data/lib/haveapi/parameters/resource.rb +7 -7
  42. data/lib/haveapi/parameters/typed.rb +6 -9
  43. data/lib/haveapi/params.rb +38 -45
  44. data/lib/haveapi/resource.rb +8 -8
  45. data/lib/haveapi/resources/action_state.rb +11 -19
  46. data/lib/haveapi/server.rb +102 -107
  47. data/lib/haveapi/spec/api_response.rb +1 -1
  48. data/lib/haveapi/spec/helpers.rb +1 -1
  49. data/lib/haveapi/spec/mock_action.rb +11 -10
  50. data/lib/haveapi/spec/spec_methods.rb +9 -8
  51. data/lib/haveapi/tasks/yard.rb +2 -2
  52. data/lib/haveapi/types.rb +0 -3
  53. data/lib/haveapi/validator.rb +6 -3
  54. data/lib/haveapi/validator_chain.rb +9 -8
  55. data/lib/haveapi/validators/acceptance.rb +6 -6
  56. data/lib/haveapi/validators/confirmation.rb +2 -3
  57. data/lib/haveapi/validators/exclusion.rb +1 -1
  58. data/lib/haveapi/validators/format.rb +1 -1
  59. data/lib/haveapi/validators/inclusion.rb +1 -1
  60. data/lib/haveapi/validators/length.rb +12 -11
  61. data/lib/haveapi/validators/numericality.rb +14 -13
  62. data/lib/haveapi/validators/presence.rb +4 -3
  63. data/lib/haveapi/version.rb +2 -2
  64. data/lib/haveapi.rb +2 -3
  65. data/spec/.rubocop.yml +4 -0
  66. data/spec/action/dsl_spec.rb +18 -18
  67. data/spec/authorization_spec.rb +8 -8
  68. data/spec/common_spec.rb +2 -1
  69. data/spec/documentation_spec.rb +2 -9
  70. data/spec/envelope_spec.rb +2 -2
  71. data/spec/hooks_spec.rb +12 -12
  72. data/spec/parameters/typed_spec.rb +6 -6
  73. data/spec/params_spec.rb +22 -24
  74. data/spec/resource_spec.rb +5 -7
  75. data/spec/spec_helper.rb +0 -1
  76. data/spec/validators/acceptance_spec.rb +1 -1
  77. data/spec/validators/confirmation_spec.rb +5 -5
  78. data/spec/validators/exclusion_spec.rb +3 -3
  79. data/spec/validators/format_spec.rb +2 -2
  80. data/spec/validators/inclusion_spec.rb +4 -4
  81. data/spec/validators/length_spec.rb +23 -23
  82. data/spec/validators/numericality_spec.rb +13 -13
  83. data/spec/validators/presence_spec.rb +3 -3
  84. metadata +49 -48
data/lib/haveapi/hooks.rb CHANGED
@@ -77,7 +77,7 @@ module HaveAPI
77
77
  # p MyClass.call_hooks(:myhook, args: [1, 2, 3], initial: {counter: 0})
78
78
  # => {:counter=>5}
79
79
  module Hooks
80
- INSTANCE_VARIABLE = '@_haveapi_hooks'
80
+ INSTANCE_VARIABLE = '@_haveapi_hooks'.freeze
81
81
 
82
82
  # Register a hook defined by `klass` with `name`.
83
83
  # @param klass [Class] an instance of Class, that is class name, not it's instance
@@ -116,7 +116,7 @@ module HaveAPI
116
116
  instance.instance_variable_set(INSTANCE_VARIABLE, hooks)
117
117
  end
118
118
 
119
- hooks[name] ||= {listeners: []}
119
+ hooks[name] ||= { listeners: [] }
120
120
  hooks[name][:listeners] << block
121
121
  end
122
122
 
@@ -143,36 +143,37 @@ module HaveAPI
143
143
  # @param initial [Hash] initial return value
144
144
  # @param instance [Boolean] call instance hooks or not; nil means auto-detect
145
145
  def self.call_for(
146
- klass,
147
- name,
148
- where = nil,
149
- args: [],
150
- kwargs: {},
151
- initial: {},
152
- instance: nil
146
+ klass,
147
+ name,
148
+ where = nil,
149
+ args: [],
150
+ kwargs: {},
151
+ initial: {},
152
+ instance: nil
153
153
  )
154
154
  classified = hook_classify(klass)
155
155
 
156
- if (instance.nil? && !classified.is_a?(Class)) || instance
157
- all_hooks = klass.instance_variable_get(INSTANCE_VARIABLE)
156
+ all_hooks = if (instance.nil? && !classified.is_a?(Class)) || instance
157
+ klass.instance_variable_get(INSTANCE_VARIABLE)
158
158
 
159
- else
160
- all_hooks = @hooks[classified]
161
- end
159
+ else
160
+ @hooks[classified]
161
+ end
162
162
 
163
163
  catch(:stop) do
164
164
  return initial unless all_hooks
165
165
  return initial unless all_hooks[name]
166
+
166
167
  hooks = all_hooks[name][:listeners]
167
168
  return initial unless hooks
168
169
 
169
170
  hooks.each do |hook|
170
- if where
171
- ret = where.instance_exec(initial, *args, **kwargs, &hook)
171
+ ret = if where
172
+ where.instance_exec(initial, *args, **kwargs, &hook)
172
173
 
173
- else
174
- ret = hook.call(initial, *args, **kwargs)
175
- end
174
+ else
175
+ hook.call(initial, *args, **kwargs)
176
+ end
176
177
 
177
178
  initial.update(ret) if ret
178
179
  end
@@ -195,60 +196,60 @@ module HaveAPI
195
196
  module ClassMethods
196
197
  # Register a hook named `name`.
197
198
  def has_hook(name, opts = {})
198
- Hooks.register_hook(self.to_s, name, opts)
199
+ Hooks.register_hook(to_s, name, opts)
199
200
  end
200
201
 
201
202
  # Connect `block` to registered hook with `name`.
202
- def connect_hook(name, &block)
203
- Hooks.connect_hook(self.to_s, name, &block)
203
+ def connect_hook(name, &)
204
+ Hooks.connect_hook(to_s, name, &)
204
205
  end
205
206
 
206
207
  # Call all hooks for `name`. see {Hooks.call_for}.
207
- def call_hooks(*args, **kwargs)
208
- Hooks.call_for(self.to_s, *args, **kwargs)
208
+ def call_hooks(*, **)
209
+ Hooks.call_for(to_s, *, **)
209
210
  end
210
211
  end
211
212
 
212
213
  module InstanceMethods
213
214
  # Call all instance and class hooks.
214
- def call_hooks_for(*args, **kwargs)
215
- ret = call_instance_hooks_for(*args, **kwargs)
215
+ def call_hooks_for(*, **kwargs)
216
+ ret = call_instance_hooks_for(*, **kwargs)
216
217
 
217
218
  kwargs[:initial] = ret
218
- call_class_hooks_for(*args, **kwargs)
219
+ call_class_hooks_for(*, **kwargs)
219
220
  end
220
221
 
221
222
  # Call only instance hooks.
222
223
  def call_instance_hooks_for(name, where = nil, args: [], kwargs: {}, initial: {})
223
- Hooks.call_for(self, name, where, args: args, kwargs: kwargs, initial: initial)
224
+ Hooks.call_for(self, name, where, args:, kwargs:, initial:)
224
225
  end
225
226
 
226
227
  # Call only class hooks.
227
- def call_class_hooks_for(name, where = nil, args: [], kwargs: {}, initial: {})
228
- Hooks.call_for(self.class, name, where, args: args, kwargs: kwargs, initial: initial)
228
+ def call_class_hooks_for(name, where = nil, args: [], kwargs: {}, initial: {})
229
+ Hooks.call_for(self.class, name, where, args:, kwargs:, initial:)
229
230
  end
230
231
 
231
232
  # Call hooks for different `klass`.
232
- def call_hooks_as_for(klass, *args, **kwargs)
233
- ret = call_instance_hooks_as_for(klass, *args, **kwargs)
233
+ def call_hooks_as_for(klass, *, **kwargs)
234
+ ret = call_instance_hooks_as_for(klass, *, **kwargs)
234
235
 
235
236
  kwargs[:initial] = ret
236
- call_class_hooks_as_for(klass.class, *args, **kwargs)
237
+ call_class_hooks_as_for(klass.class, *, **kwargs)
237
238
  end
238
239
 
239
240
  # Call only instance hooks for different `klass`.
240
- def call_instance_hooks_as_for(klass, *args, **kwargs)
241
- Hooks.call_for(klass, *args, **kwargs)
241
+ def call_instance_hooks_as_for(klass, *, **)
242
+ Hooks.call_for(klass, *, **)
242
243
  end
243
244
 
244
245
  # Call only class hooks for different `klass`.
245
- def call_class_hooks_as_for(klass, *args, **kwargs)
246
- Hooks.call_for(klass, *args, **kwargs)
246
+ def call_class_hooks_as_for(klass, *, **)
247
+ Hooks.call_for(klass, *, **)
247
248
  end
248
249
 
249
250
  # Connect instance level hook `name` to `block`.
250
- def connect_hook(name, &block)
251
- Hooks.connect_instance_hook(self, name, &block)
251
+ def connect_hook(name, &)
252
+ Hooks.connect_instance_hook(self, name, &)
252
253
  end
253
254
  end
254
255
 
@@ -6,7 +6,7 @@ module HaveAPI
6
6
 
7
7
  def self.describe
8
8
  {
9
- namespace: namespace
9
+ namespace:
10
10
  }
11
11
  end
12
12
 
@@ -14,38 +14,37 @@ module HaveAPI
14
14
  # Every model adapter must register itself using this method.
15
15
  def register
16
16
  ModelAdapter.adapters ||= []
17
- ModelAdapter.adapters << Kernel.const_get(self.to_s)
17
+ ModelAdapter.adapters << Kernel.const_get(to_s)
18
18
  end
19
19
 
20
20
  # Returns an adapter suitable for `layout` and `obj`.
21
21
  # Adapters are iterated over and the first to return true to handle?()
22
22
  # is returned.
23
23
  def for(layout, obj)
24
- return ModelAdapters::Hash if !obj || %i(hash hash_list).include?(layout)
25
- adapter = @adapters.detect { |adapter| adapter.handle?(layout, obj) }
24
+ return ModelAdapters::Hash if !obj || %i[hash hash_list].include?(layout)
25
+
26
+ adapter = @adapters.detect { |a| a.handle?(layout, obj) }
26
27
  adapter || ModelAdapters::Hash
27
28
  end
28
29
 
29
30
  # Shortcut to Input::clean.
30
- def input_clean(*args)
31
- self::Input.clean(*args)
31
+ def input_clean(*)
32
+ self::Input.clean(*)
32
33
  end
33
34
 
34
35
  # Shortcut to get an instance of Input model adapter.
35
- def input(*args)
36
- self::Input.new(*args)
36
+ def input(*)
37
+ self::Input.new(*)
37
38
  end
38
39
 
39
40
  # Shortcut to get an instance of Output model adapter.
40
- def output(*args)
41
- self::Output.new(*args)
41
+ def output(*)
42
+ self::Output.new(*)
42
43
  end
43
44
 
44
45
  # Override this method to load validators from `model`
45
46
  # to `params`.
46
- def load_validators(model, params)
47
-
48
- end
47
+ def load_validators(model, params); end
49
48
 
50
49
  # Called when mounting the API. Model adapters may use this method
51
50
  # to add custom meta parameters to `action`. `direction` is one of
@@ -63,9 +62,7 @@ module HaveAPI
63
62
  # Subclass this class in your adapter and reimplement
64
63
  # necessary methods.
65
64
  class Input
66
- def self.used_by(action)
67
-
68
- end
65
+ def self.used_by(action); end
69
66
 
70
67
  def initialize(input)
71
68
  @input = input
@@ -83,17 +80,13 @@ module HaveAPI
83
80
  end
84
81
 
85
82
  # Return model instance from a raw input resource parameter.
86
- def self.clean(model, raw, extra)
87
-
88
- end
83
+ def self.clean(model, raw, extra); end
89
84
  end
90
85
 
91
86
  # Subclass this class in your adapter and reimplement
92
87
  # necessary methods.
93
88
  class Output
94
- def self.used_by(action)
95
-
96
- end
89
+ def self.used_by(action); end
97
90
 
98
91
  def initialize(context, obj)
99
92
  @context = context
@@ -102,14 +95,10 @@ module HaveAPI
102
95
 
103
96
  # Return true if input parameters contain parameter
104
97
  # with `name`.
105
- def has_param?(name)
106
-
107
- end
98
+ def has_param?(name); end
108
99
 
109
100
  # Return a parameter in an appropriate format to be sent to a client.
110
- def [](name)
111
-
112
- end
101
+ def [](name); end
113
102
 
114
103
  def meta
115
104
  {}
@@ -6,7 +6,7 @@ module HaveAPI::ModelAdapters
6
6
  register
7
7
 
8
8
  def self.handle?(layout, klass)
9
- klass < ::ActiveRecord::Base && %i(object object_list).include?(layout)
9
+ klass < ::ActiveRecord::Base && %i[object object_list].include?(layout)
10
10
  end
11
11
 
12
12
  def self.load_validators(model, params)
@@ -34,10 +34,10 @@ module HaveAPI::ModelAdapters
34
34
  # it well, it is not necessary to fix.
35
35
  args.concat(ar_default_includes).uniq
36
36
 
37
- if !args.empty?
38
- q.includes(*args)
39
- else
37
+ if args.empty?
40
38
  q
39
+ else
40
+ q.includes(*args)
41
41
  end
42
42
  end
43
43
 
@@ -45,6 +45,7 @@ module HaveAPI::ModelAdapters
45
45
  # in an array of symbols and hashes.
46
46
  def ar_parse_includes(raw)
47
47
  return @ar_parsed_includes if @ar_parsed_includes
48
+
48
49
  @ar_parsed_includes = ar_inner_includes(raw).select do |inc|
49
50
  # Drop associations that are not registered in the AR:
50
51
  # The API resource may have associations that are not based on
@@ -70,7 +71,7 @@ module HaveAPI::ModelAdapters
70
71
  if assoc.index('__')
71
72
  tmp = {}
72
73
  parts = assoc.split('__')
73
- tmp[parts.first.to_sym] = ar_inner_includes([parts[1..-1].join('__')])
74
+ tmp[parts.first.to_sym] = ar_inner_includes([parts[1..].join('__')])
74
75
 
75
76
  args << tmp
76
77
  else
@@ -115,39 +116,37 @@ module HaveAPI::ModelAdapters
115
116
  action.meta(:object) do
116
117
  output do
117
118
  custom :path_params, label: 'URL parameters',
118
- desc: 'An array of parameters needed to resolve URL to this object'
119
+ desc: 'An array of parameters needed to resolve URL to this object'
119
120
  bool :resolved, label: 'Resolved', desc: 'True if the association is resolved'
120
121
  end
121
122
  end
122
123
 
123
- if %i(object object_list).include?(action.input.layout)
124
- clean = Proc.new do |raw|
125
- if raw.is_a?(String)
126
- raw.strip.split(',')
127
- elsif raw.is_a?(Array)
128
- raw
129
- else
130
- nil
131
- end
132
- end
124
+ return unless %i[object object_list].include?(action.input.layout)
133
125
 
134
- desc = <<END
135
- A list of names of associated resources separated by a comma.
136
- Nested associations are declared with '__' between resource names.
137
- For example, 'user,node' will resolve the two associations.
138
- To resolve further associations of node, use e.g. 'user,node__location',
139
- to go even deeper, use e.g. 'user,node__location__environment'.
140
- END
141
-
142
- action.meta(:global) do
143
- input do
144
- custom :includes, label: 'Included associations',
145
- desc: desc, &clean
146
- end
126
+ clean = proc do |raw|
127
+ if raw.is_a?(String)
128
+ raw.strip.split(',')
129
+ elsif raw.is_a?(Array)
130
+ raw
147
131
  end
132
+ end
148
133
 
149
- action.send(:include, Action::InstanceMethods)
134
+ desc = <<~END
135
+ A list of names of associated resources separated by a comma.
136
+ Nested associations are declared with '__' between resource names.
137
+ For example, 'user,node' will resolve the two associations.
138
+ To resolve further associations of node, use e.g. 'user,node__location',
139
+ to go even deeper, use e.g. 'user,node__location__environment'.
140
+ END
141
+
142
+ action.meta(:global) do
143
+ input do
144
+ custom :includes, label: 'Included associations',
145
+ desc:, &clean
146
+ end
150
147
  end
148
+
149
+ action.send(:include, Action::InstanceMethods)
151
150
  end
152
151
 
153
152
  def has_param?(name)
@@ -169,14 +168,14 @@ END
169
168
  def meta
170
169
  res = @context.action.resource
171
170
 
172
- if @context.action.name.demodulize == 'Index' \
171
+ params = if @context.action.name.demodulize == 'Index' \
173
172
  && !@context.action.resolve \
174
173
  && res.const_defined?(:Show)
175
- params = res::Show.resolve_path_params(@object)
174
+ res::Show.resolve_path_params(@object)
176
175
 
177
- else
178
- params = @context.action.resolve_path_params(@object)
179
- end
176
+ else
177
+ @context.action.resolve_path_params(@object)
178
+ end
180
179
 
181
180
  {
182
181
  path_params: params.is_a?(Array) ? params : [params],
@@ -185,6 +184,7 @@ END
185
184
  end
186
185
 
187
186
  protected
187
+
188
188
  # Return representation of an associated resource `param`
189
189
  # with its instance in `val`.
190
190
  #
@@ -223,7 +223,7 @@ END
223
223
  @context.action_instance = push_ins
224
224
  @context.action = push_cls
225
225
 
226
- fail "#{res_show.to_s} resolve failed" unless ret[0]
226
+ raise "#{res_show} resolve failed" unless ret[0]
227
227
 
228
228
  ret[1][res_show.output.namespace].update({
229
229
  _meta: ret[1][:_meta].update(resolved: true)
@@ -234,8 +234,8 @@ END
234
234
  param.value_id => val.send(res_output[param.value_id].db_name),
235
235
  param.value_label => val.send(res_output[param.value_label].db_name),
236
236
  _meta: {
237
- :path_params => args.is_a?(Array) ? args : [args],
238
- :resolved => false
237
+ path_params: args.is_a?(Array) ? args : [args],
238
+ resolved: false
239
239
  }
240
240
  }
241
241
  end
@@ -244,49 +244,39 @@ END
244
244
  # Should an association with `name` be resolved?
245
245
  def includes_include?(name)
246
246
  includes = @context.action_instance.meta[:includes]
247
- return unless includes
247
+ return false unless includes
248
248
 
249
249
  name = name.to_sym
250
250
 
251
251
  if @context.action_instance.flags[:inner_assoc]
252
252
  # This action is called as an association of parent resource.
253
253
  # Meta includes are already parsed and can be accessed directly.
254
- includes.each do |v|
255
- if v.is_a?(::Hash)
256
- return true if v.has_key?(name)
257
- else
258
- return true if v == name
259
- end
260
- end
261
-
262
- false
263
-
264
254
  else
265
255
  # This action is the one that was called by the user.
266
256
  # Meta includes contains an array of strings as was sent
267
257
  # by the user. The parsed includes must be fetched from
268
258
  # the action itself.
269
259
  includes = @context.action_instance.ar_parse_includes([])
260
+ end
270
261
 
271
- includes.each do |v|
272
- if v.is_a?(::Hash)
273
- return true if v.has_key?(name)
274
- else
275
- return true if v == name
276
- end
262
+ includes.each do |v|
263
+ if v.is_a?(::Hash)
264
+ return true if v.has_key?(name)
265
+ elsif v == name
266
+ return true
277
267
  end
278
-
279
- false
280
268
  end
269
+
270
+ false
281
271
  end
282
272
 
283
273
  # Create an array of includes that is passed to child association.
284
274
  def includes_pass_on_to(assoc)
285
275
  parsed = if @context.action_instance.flags[:inner_assoc]
286
- @context.action_instance.meta[:includes]
287
- else
288
- @context.action_instance.ar_parse_includes([])
289
- end
276
+ @context.action_instance.meta[:includes]
277
+ else
278
+ @context.action_instance.ar_parse_includes([])
279
+ end
290
280
 
291
281
  ret = []
292
282
 
@@ -324,7 +314,7 @@ END
324
314
 
325
315
  handle ::ActiveModel::Validations::ExclusionValidator do |v|
326
316
  opts = {
327
- values: v.options[:in].map { |v| v }
317
+ values: v.options[:in]
328
318
  }
329
319
  opts[:message] = v.options[:message] if v.options[:message]
330
320
 
@@ -342,7 +332,7 @@ END
342
332
 
343
333
  handle ::ActiveModel::Validations::InclusionValidator do |v|
344
334
  opts = {
345
- values: v.options[:in].map { |v| v }
335
+ values: v.options[:in]
346
336
  }
347
337
  opts[:message] = v.options[:message] if v.options[:message]
348
338
 
@@ -402,13 +392,13 @@ END
402
392
 
403
393
  def translate(v)
404
394
  self.class.handlers.each do |klass, translator|
405
- if v.is_a?(klass)
406
- v.attributes.each do |attr|
407
- @attr = attr
408
- instance_exec(v, &translator)
409
- end
410
- break
395
+ next unless v.is_a?(klass)
396
+
397
+ v.attributes.each do |attr|
398
+ @attr = attr
399
+ instance_exec(v, &translator)
411
400
  end
401
+ break
412
402
  end
413
403
  end
414
404
  end
@@ -1,6 +1,5 @@
1
1
  module HaveAPI
2
2
  module OutputFormatters
3
-
4
3
  end
5
4
 
6
5
  class OutputFormatter
@@ -29,7 +28,7 @@ module HaveAPI
29
28
  end
30
29
  end
31
30
 
32
- @formatter.nil? ? false : true
31
+ !@formatter.nil?
33
32
  end
34
33
 
35
34
  def format(status, response, message = nil, errors = nil, version: true)
@@ -45,14 +44,15 @@ module HaveAPI
45
44
  end
46
45
 
47
46
  protected
48
- def header(status, response, message = nil, errors = nil, version)
47
+
48
+ def header(status, response, message = nil, errors = nil, version = nil)
49
49
  ret = {}
50
50
  ret[:version] = HaveAPI::PROTOCOL_VERSION if version
51
51
  ret.update({
52
- status: status,
53
- response: response,
54
- message: message,
55
- errors: errors
52
+ status:,
53
+ response:,
54
+ message:,
55
+ errors:
56
56
  })
57
57
  ret
58
58
  end
@@ -7,7 +7,7 @@ module HaveAPI::OutputFormatters
7
7
  @types ||= []
8
8
  @types += args
9
9
 
10
- HaveAPI::OutputFormatter.register(Kernel.const_get(self.to_s)) unless @registered
10
+ HaveAPI::OutputFormatter.register(Kernel.const_get(to_s)) unless @registered
11
11
  @registered = true
12
12
  end
13
13
 
@@ -22,8 +22,6 @@ module HaveAPI::OutputFormatters
22
22
  self.class.types.first
23
23
  end
24
24
 
25
- def format(response)
26
-
27
- end
25
+ def format(response); end
28
26
  end
29
27
  end
@@ -4,8 +4,8 @@ module HaveAPI::Parameters
4
4
  :choices, :value_params
5
5
 
6
6
  def initialize(resource, name: nil, label: nil, desc: nil,
7
- choices: nil, value_id: :id, value_label: :label, required: nil,
8
- db_name: nil, fetch: nil)
7
+ choices: nil, value_id: :id, value_label: :label, required: nil,
8
+ db_name: nil, fetch: nil)
9
9
  @resource = resource
10
10
  @resource_path = build_resource_path(resource)
11
11
  @name = name || resource.resource_name.underscore.to_sym
@@ -17,7 +17,7 @@ module HaveAPI::Parameters
17
17
  @required = required
18
18
  @db_name = db_name
19
19
  @extra = {
20
- fetch: fetch
20
+ fetch:
21
21
  }
22
22
  end
23
23
 
@@ -65,7 +65,7 @@ module HaveAPI::Parameters
65
65
  value: context.action_prepare && {
66
66
  path: val_path,
67
67
  method: val_method,
68
- help: "#{val_path}?method=#{val_method}",
68
+ help: "#{val_path}?method=#{val_method}"
69
69
  },
70
70
  choices: {
71
71
  path: choices_path,
@@ -76,13 +76,13 @@ module HaveAPI::Parameters
76
76
  end
77
77
 
78
78
  def validate_build_output
79
- %i(value_id value_label).each do |name|
79
+ %i[value_id value_label].each do |name|
80
80
  v = instance_variable_get("@#{name}")
81
81
 
82
82
  [show_action, show_index].each do |klass|
83
83
  next unless klass.instance_variable_get('@output')[v].nil?
84
84
 
85
- fail "association to '#{@resource}': value_label '#{v}' is not an output parameter of '#{klass}'"
85
+ raise "association to '#{@resource}': value_label '#{v}' is not an output parameter of '#{klass}'"
86
86
  end
87
87
  end
88
88
  end
@@ -106,6 +106,7 @@ module HaveAPI::Parameters
106
106
  end
107
107
 
108
108
  private
109
+
109
110
  def build_resource_path(r)
110
111
  path = []
111
112
  top_module = Kernel
@@ -115,7 +116,6 @@ module HaveAPI::Parameters
115
116
 
116
117
  begin
117
118
  top_module.obj_type
118
-
119
119
  rescue NoMethodError
120
120
  next
121
121
  end
@@ -2,7 +2,7 @@ require 'date'
2
2
 
3
3
  module HaveAPI::Parameters
4
4
  class Typed
5
- ATTRIBUTES = %i(label desc type db_name default fill clean protected load_validators)
5
+ ATTRIBUTES = %i[label desc type db_name default fill clean protected load_validators].freeze
6
6
 
7
7
  attr_reader :name, :label, :desc, :type, :default
8
8
 
@@ -14,14 +14,14 @@ module HaveAPI::Parameters
14
14
  @label = myargs.delete(:label) || name.to_s.capitalize
15
15
  @layout = :custom
16
16
 
17
- (ATTRIBUTES - %i(label)).each do |attr|
17
+ (ATTRIBUTES - %i[label]).each do |attr|
18
18
  instance_variable_set("@#{attr}", myargs.delete(attr))
19
19
  end
20
20
 
21
21
  @type ||= String
22
22
 
23
23
  @validators = HaveAPI::ValidatorChain.new(myargs) unless myargs.empty?
24
- fail "unused arguments #{myargs}" unless myargs.empty?
24
+ raise "unused arguments #{myargs}" unless myargs.empty?
25
25
  end
26
26
 
27
27
  def db_name
@@ -52,7 +52,7 @@ module HaveAPI::Parameters
52
52
  type: @type ? @type.to_s : String.to_s,
53
53
  validators: @validators ? @validators.describe : {},
54
54
  default: @default,
55
- protected: @protected || false,
55
+ protected: @protected || false
56
56
  }
57
57
  end
58
58
 
@@ -75,7 +75,7 @@ module HaveAPI::Parameters
75
75
  def clean(raw)
76
76
  return instance_exec(raw, &@clean) if @clean
77
77
 
78
- val = if raw.nil?
78
+ if raw.nil?
79
79
  @default
80
80
 
81
81
  elsif @type.nil?
@@ -93,16 +93,13 @@ module HaveAPI::Parameters
93
93
  elsif @type == ::Datetime
94
94
  begin
95
95
  DateTime.iso8601(raw).to_time
96
-
97
96
  rescue ArgumentError
98
- raise HaveAPI::ValidationError.new("not in ISO 8601 format '#{raw}'")
97
+ raise HaveAPI::ValidationError, "not in ISO 8601 format '#{raw}'"
99
98
  end
100
99
 
101
100
  else
102
101
  raw
103
102
  end
104
-
105
- val
106
103
  end
107
104
 
108
105
  def validate(v, params)