haveapi 0.20.0 → 0.21.1

Sign up to get free protection for your applications and to get access to all the features.
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)