haveapi 0.18.1 → 0.19.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.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/haveapi.gemspec +2 -1
  3. data/lib/haveapi/action.rb +72 -31
  4. data/lib/haveapi/authentication/base.rb +1 -1
  5. data/lib/haveapi/authentication/basic/provider.rb +2 -2
  6. data/lib/haveapi/authentication/chain.rb +4 -4
  7. data/lib/haveapi/authentication/oauth2/config.rb +62 -15
  8. data/lib/haveapi/authentication/oauth2/provider.rb +111 -17
  9. data/lib/haveapi/authentication/oauth2/revoke_endpoint.rb +36 -0
  10. data/lib/haveapi/authentication/token/config.rb +1 -0
  11. data/lib/haveapi/authorization.rb +19 -12
  12. data/lib/haveapi/client_examples/js_client.rb +11 -1
  13. data/lib/haveapi/client_examples/php_client.rb +43 -1
  14. data/lib/haveapi/context.rb +21 -2
  15. data/lib/haveapi/example.rb +9 -9
  16. data/lib/haveapi/hooks.rb +23 -23
  17. data/lib/haveapi/metadata.rb +1 -1
  18. data/lib/haveapi/model_adapter.rb +14 -14
  19. data/lib/haveapi/model_adapters/active_record.rb +20 -20
  20. data/lib/haveapi/output_formatter.rb +4 -4
  21. data/lib/haveapi/output_formatters/base.rb +1 -1
  22. data/lib/haveapi/parameters/resource.rb +22 -22
  23. data/lib/haveapi/parameters/typed.rb +7 -7
  24. data/lib/haveapi/params.rb +24 -22
  25. data/lib/haveapi/resource.rb +9 -3
  26. data/lib/haveapi/resources/action_state.rb +16 -16
  27. data/lib/haveapi/route.rb +3 -2
  28. data/lib/haveapi/server.rb +113 -98
  29. data/lib/haveapi/spec/mock_action.rb +7 -7
  30. data/lib/haveapi/spec/spec_methods.rb +8 -8
  31. data/lib/haveapi/tasks/yard.rb +2 -2
  32. data/lib/haveapi/validator.rb +13 -13
  33. data/lib/haveapi/validator_chain.rb +6 -6
  34. data/lib/haveapi/validators/acceptance.rb +2 -2
  35. data/lib/haveapi/validators/confirmation.rb +4 -4
  36. data/lib/haveapi/validators/exclusion.rb +4 -4
  37. data/lib/haveapi/validators/format.rb +4 -4
  38. data/lib/haveapi/validators/inclusion.rb +3 -3
  39. data/lib/haveapi/validators/length.rb +1 -1
  40. data/lib/haveapi/validators/numericality.rb +3 -3
  41. data/lib/haveapi/validators/presence.rb +2 -2
  42. data/lib/haveapi/version.rb +1 -1
  43. data/lib/haveapi/views/version_page/auth_body.erb +6 -4
  44. data/lib/haveapi/views/version_page/resource_body.erb +2 -0
  45. data/lib/haveapi.rb +1 -0
  46. data/spec/authorization_spec.rb +28 -28
  47. data/spec/envelope_spec.rb +4 -4
  48. data/spec/parameters/typed_spec.rb +3 -3
  49. data/spec/params_spec.rb +2 -2
  50. data/spec/validators/acceptance_spec.rb +2 -2
  51. data/spec/validators/confirmation_spec.rb +4 -4
  52. data/spec/validators/exclusion_spec.rb +2 -2
  53. data/spec/validators/format_spec.rb +5 -5
  54. data/spec/validators/inclusion_spec.rb +8 -8
  55. data/spec/validators/presence_spec.rb +1 -1
  56. metadata +19 -4
@@ -1,20 +1,27 @@
1
1
  module HaveAPI
2
2
  class Authorization
3
3
  def initialize(&block)
4
- @block = block
4
+ @blocks = [block]
5
5
  end
6
6
 
7
7
  # Returns true if user is authorized.
8
8
  # Block must call allow to authorize user, default rule is deny.
9
- def authorized?(user)
9
+ def authorized?(user, path_params)
10
10
  @restrict = []
11
11
 
12
12
  catch(:rule) do
13
- instance_exec(user, &@block) if @block
14
- deny # will not be called if block throws allow
13
+ @blocks.each do |block|
14
+ instance_exec(user, path_params, &block)
15
+ end
16
+
17
+ deny # will not be called if some block throws allow
15
18
  end
16
19
  end
17
20
 
21
+ def prepend_block(block)
22
+ @blocks.insert(0, block)
23
+ end
24
+
18
25
  # Apply restrictions on query which selects objects from database.
19
26
  # Most common usage is restrict user to access only objects he owns.
20
27
  def restrict(**kwargs)
@@ -22,22 +29,22 @@ module HaveAPI
22
29
  end
23
30
 
24
31
  # Restrict parameters client can set/change.
25
- # [whitelist] allow only listed parameters
26
- # [blacklist] allow all parameters except listed ones
32
+ # @param whitelist [Array<Symbol>] allow only listed parameters
33
+ # @param blacklist [Array<Symbol>] allow all parameters except listed ones
27
34
  def input(whitelist: nil, blacklist: nil)
28
35
  @input = {
29
- whitelist: whitelist,
30
- blacklist: blacklist,
36
+ whitelist: whitelist,
37
+ blacklist: blacklist,
31
38
  }
32
39
  end
33
40
 
34
41
  # Restrict parameters client can retrieve.
35
- # [whitelist] allow only listed parameters
36
- # [blacklist] allow all parameters except listed ones
42
+ # @param whitelist [Array<Symbol>] allow only listed parameters
43
+ # @param blacklist [Array<Symbol>] allow all parameters except listed ones
37
44
  def output(whitelist: nil, blacklist: nil)
38
45
  @output = {
39
- whitelist: whitelist,
40
- blacklist: blacklist,
46
+ whitelist: whitelist,
47
+ blacklist: blacklist,
41
48
  }
42
49
  end
43
50
 
@@ -51,7 +51,17 @@ api.authenticate("token", {
51
51
  END
52
52
 
53
53
  when :oauth2
54
- '// OAuth2 is not supported by HaveAPI JavaScript client.'
54
+ <<END
55
+ #{init}
56
+ // The JavaScript client must be configured with OAuth2 access token, it does not
57
+ // support the authorization procedure to obtain a new access token.
58
+ var accessToken = {
59
+ access_token: "the access token"
60
+ };
61
+
62
+ // The client is authenticated immediately, no need for a callback
63
+ api.authenticate("oauth2", {access_token: accessToken});
64
+ END
55
65
  end
56
66
  end
57
67
 
@@ -35,7 +35,49 @@ $api->authenticate("token", ["token" => $savedToken]);
35
35
  END
36
36
 
37
37
  when :oauth2
38
- '// OAuth2 is not supported by HaveAPI PHP client.'
38
+ <<END
39
+ // OAuth2 requires session
40
+ session_start();
41
+
42
+ // Client instance
43
+ #{init}
44
+ // Check if we already have an access token
45
+ if (isset($_SESSION["access_token"])) {
46
+ // We're already authenticated, reuse the existing access token
47
+ $api->authenticate("oauth2", ["access_token" => $_SESSION["access_token"]]);
48
+
49
+ } else {
50
+ // Follow the OAuth2 authorization process to get an access token using
51
+ // authorization code
52
+ $api->authenticate("oauth2", [
53
+ // Client id and secret are given by the API server
54
+ "client_id" => "your client id",
55
+ "client_secret" => "your client secret",
56
+
57
+ // This example code should run on the URL below
58
+ "redirect_uri" => "https://your-client.tld/oauth2-callback",
59
+
60
+ // Scopes are specific to the API implementation
61
+ "scope" => "all",
62
+ ]);
63
+
64
+ $provider = $api->getAuthenticationProvider();
65
+
66
+ // We don't have authorization code yet, request one
67
+ if (!isset($_GET['code'])) {
68
+ // Redirect the user to the authorization endpoint
69
+ $provider->requestAuthorizationCode();
70
+ exit;
71
+
72
+ } else {
73
+ // Request access token using the token endpoint
74
+ $provider->requestAccessToken();
75
+
76
+ // Store the access token in the session
77
+ $_SESSION['access_token'] = $provider->jsonSerialize();
78
+ }
79
+ }
80
+ END
39
81
  end
40
82
  end
41
83
 
@@ -1,12 +1,12 @@
1
1
  module HaveAPI
2
2
  class Context
3
3
  attr_accessor :server, :version, :request, :resource, :action, :path, :args,
4
- :params, :current_user, :authorization, :endpoint,
4
+ :params, :current_user, :authorization, :endpoint, :resource_path,
5
5
  :action_instance, :action_prepare, :layout
6
6
 
7
7
  def initialize(server, version: nil, request: nil, resource: [], action: nil,
8
8
  path: nil, args: nil, params: nil, user: nil,
9
- authorization: nil, endpoint: nil)
9
+ authorization: nil, endpoint: nil, resource_path: [])
10
10
  @server = server
11
11
  @version = version
12
12
  @request = request
@@ -18,6 +18,7 @@ module HaveAPI
18
18
  @current_user = user
19
19
  @authorization = authorization
20
20
  @endpoint = endpoint
21
+ @resource_path = resource_path
21
22
  end
22
23
 
23
24
  def resolved_path
@@ -71,6 +72,24 @@ module HaveAPI
71
72
  path_for(action, call_path_params(action, obj))
72
73
  end
73
74
 
75
+ def path_params_from_args
76
+ ret = {}
77
+ return ret if args.nil?
78
+
79
+ my_args = args.clone
80
+
81
+ path.scan(/\{([a-zA-Z\-_]+)\}/) do |match|
82
+ path_param = match.first
83
+ ret[path_param] = my_args.shift
84
+ end
85
+
86
+ ret
87
+ end
88
+
89
+ def action_scope
90
+ resource_path.map(&:downcase).join('.') + '#' + action.action_name.underscore
91
+ end
92
+
74
93
  private
75
94
  def resolve_arg!(path, arg)
76
95
  path.sub!(/\{[a-zA-Z\-_]+\}/, arg.to_s)
@@ -58,15 +58,15 @@ module HaveAPI
58
58
  def describe(context)
59
59
  if provided?
60
60
  {
61
- title: @title,
62
- comment: @comment,
63
- path_params: @path_params,
64
- request: filter_input_params(context, @request),
65
- response: filter_output_params(context, @response),
66
- status: @status.nil? ? true : @status,
67
- message: @message,
68
- errors: @errors,
69
- http_status: @http_status || 200,
61
+ title: @title,
62
+ comment: @comment,
63
+ path_params: @path_params,
64
+ request: filter_input_params(context, @request),
65
+ response: filter_output_params(context, @response),
66
+ status: @status.nil? ? true : @status,
67
+ message: @message,
68
+ errors: @errors,
69
+ http_status: @http_status || 200,
70
70
  }
71
71
  else
72
72
  {}
data/lib/haveapi/hooks.rb CHANGED
@@ -79,15 +79,15 @@ module HaveAPI
79
79
  module Hooks
80
80
  INSTANCE_VARIABLE = '@_haveapi_hooks'
81
81
 
82
- # Register a hook defined by +klass+ with +name+.
83
- # +klass+ is an instance of Class, that is class name, not it's instance.
84
- # +opts+ is a hash and can have following keys:
85
- # - desc - why this hook exists, when it's called
86
- # - context - the context in which given blocks are called
87
- # - args - hash of block positional arguments
88
- # - kwargs - hash of block keyword arguments
89
- # - initial - hash of initial values
90
- # - ret - hash of return values
82
+ # Register a hook defined by `klass` with `name`.
83
+ # @param klass [Class] an instance of Class, that is class name, not it's instance
84
+ # @param opts [Hash]
85
+ # @option opts [String] :desc why this hook exists, when it's called
86
+ # @option opts [String] :context the context in which given blocks are called
87
+ # @option opts [Hash] :args hash of block positional arguments
88
+ # @option opts [Hash] :kwargs hash of block keyword arguments
89
+ # @option opts [Hash] :initial - hash of initial values
90
+ # @option opts [Hash] :ret hash of return values
91
91
  def self.register_hook(klass, name, opts = {})
92
92
  classified = hook_classify(klass)
93
93
  opts[:listeners] = []
@@ -101,13 +101,13 @@ module HaveAPI
101
101
  @hooks
102
102
  end
103
103
 
104
- # Connect class hook defined in +klass+ with +name+ to +block+.
105
- # +klass+ is a class name.
104
+ # Connect class hook defined in `klass` with `name` to `block`.
105
+ # `klass` is a class name.
106
106
  def self.connect_hook(klass, name, &block)
107
107
  @hooks[hook_classify(klass)][name][:listeners] << block
108
108
  end
109
109
 
110
- # Connect instance hook from instance +klass+ with +name+ to +block+.
110
+ # Connect instance hook from instance `klass` with `name` to `block`.
111
111
  def self.connect_instance_hook(instance, name, &block)
112
112
  hooks = instance.instance_variable_get(INSTANCE_VARIABLE)
113
113
 
@@ -120,11 +120,11 @@ module HaveAPI
120
120
  hooks[name][:listeners] << block
121
121
  end
122
122
 
123
- # Call all blocks that are connected to hook in +klass+ with +name+.
123
+ # Call all blocks that are connected to hook in `klass` with `name`.
124
124
  # +klass+ may be a class name or an object instance.
125
- # If +where+ is set, the blocks are executed in it with instance_exec.
126
- # +args+ is an array of arguments given to all blocks. The first argument
127
- # to all block is always a return value from previous block or +initial+,
125
+ # If `where` is set, the blocks are executed in it with instance_exec.
126
+ # `args` is an array of arguments given to all blocks. The first argument
127
+ # to all block is always a return value from previous block or `initial`,
128
128
  # which defaults to an empty hash.
129
129
  #
130
130
  # Blocks are executed one by one in the order they were connected.
@@ -193,17 +193,17 @@ module HaveAPI
193
193
  # Classes that define hooks must include this module.
194
194
  module Hookable
195
195
  module ClassMethods
196
- # Register a hook named +name+.
196
+ # Register a hook named `name`.
197
197
  def has_hook(name, opts = {})
198
198
  Hooks.register_hook(self.to_s, name, opts)
199
199
  end
200
200
 
201
- # Connect +block+ to registered hook with +name+.
201
+ # Connect `block` to registered hook with `name`.
202
202
  def connect_hook(name, &block)
203
203
  Hooks.connect_hook(self.to_s, name, &block)
204
204
  end
205
205
 
206
- # Call all hooks for +name+. see Hooks.call_for.
206
+ # Call all hooks for `name`. see {Hooks.call_for}.
207
207
  def call_hooks(*args, **kwargs)
208
208
  Hooks.call_for(self.to_s, *args, **kwargs)
209
209
  end
@@ -228,7 +228,7 @@ module HaveAPI
228
228
  Hooks.call_for(self.class, name, where, args: args, kwargs: kwargs, initial: initial)
229
229
  end
230
230
 
231
- # Call hooks for different +klass+.
231
+ # Call hooks for different `klass`.
232
232
  def call_hooks_as_for(klass, *args, **kwargs)
233
233
  ret = call_instance_hooks_as_for(klass, *args, **kwargs)
234
234
 
@@ -236,17 +236,17 @@ module HaveAPI
236
236
  call_class_hooks_as_for(klass.class, *args, **kwargs)
237
237
  end
238
238
 
239
- # Call only instance hooks for different +klass+.
239
+ # Call only instance hooks for different `klass`.
240
240
  def call_instance_hooks_as_for(klass, *args, **kwargs)
241
241
  Hooks.call_for(klass, *args, **kwargs)
242
242
  end
243
243
 
244
- # Call only class hooks for different +klass+.
244
+ # Call only class hooks for different `klass`.
245
245
  def call_class_hooks_as_for(klass, *args, **kwargs)
246
246
  Hooks.call_for(klass, *args, **kwargs)
247
247
  end
248
248
 
249
- # Connect instance level hook +name+ to +block+.
249
+ # Connect instance level hook `name` to `block`.
250
250
  def connect_hook(name, &block)
251
251
  Hooks.connect_instance_hook(self, name, &block)
252
252
  end
@@ -6,7 +6,7 @@ module HaveAPI
6
6
 
7
7
  def self.describe
8
8
  {
9
- namespace: namespace
9
+ namespace: namespace
10
10
  }
11
11
  end
12
12
 
@@ -2,8 +2,8 @@ module HaveAPI
2
2
  # Model adapters are used to automate handling of action
3
3
  # input/output.
4
4
  #
5
- # Adapters are chosen based on the +model+ set on a HaveAPI::Resource.
6
- # If no +model+ is specified, ModelAdapters::Hash is used as a default
5
+ # Adapters are chosen based on the `model` set on a HaveAPI::Resource.
6
+ # If no `model` is specified, ModelAdapters::Hash is used as a default
7
7
  # adapter.
8
8
  #
9
9
  # All model adapters are based on this class.
@@ -17,7 +17,7 @@ module HaveAPI
17
17
  ModelAdapter.adapters << Kernel.const_get(self.to_s)
18
18
  end
19
19
 
20
- # Returns an adapter suitable for +layout+ and +obj+.
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)
@@ -41,21 +41,21 @@ module HaveAPI
41
41
  self::Output.new(*args)
42
42
  end
43
43
 
44
- # Override this method to load validators from +model+
45
- # to +params+.
44
+ # Override this method to load validators from `model`
45
+ # to `params`.
46
46
  def load_validators(model, params)
47
47
 
48
48
  end
49
49
 
50
50
  # Called when mounting the API. Model adapters may use this method
51
- # to add custom meta parameters to +action+. +direction+ is one of
52
- # +:input+ and +:output+.
51
+ # to add custom meta parameters to `action`. `direction` is one of
52
+ # `:input` and `:output`.
53
53
  def used_by(direction, action)
54
54
  case direction
55
- when :input
56
- self::Input.used_by(action)
57
- when :output
58
- self::Output.used_by(action)
55
+ when :input
56
+ self::Input.used_by(action)
57
+ when :output
58
+ self::Output.used_by(action)
59
59
  end
60
60
  end
61
61
  end
@@ -72,12 +72,12 @@ module HaveAPI
72
72
  end
73
73
 
74
74
  # Return true if input parameters contain parameter
75
- # with +name+.
75
+ # with `name`.
76
76
  def has_param?(name)
77
77
  @input.has_key?(name)
78
78
  end
79
79
 
80
- # Return parameter with +name+.
80
+ # Return parameter with `name`.
81
81
  def [](name)
82
82
  @input[name]
83
83
  end
@@ -101,7 +101,7 @@ module HaveAPI
101
101
  end
102
102
 
103
103
  # Return true if input parameters contain parameter
104
- # with +name+.
104
+ # with `name`.
105
105
  def has_param?(name)
106
106
 
107
107
  end
@@ -21,7 +21,7 @@ module HaveAPI::ModelAdapters
21
21
  module InstanceMethods
22
22
  # Helper method that sets correct ActiveRecord includes
23
23
  # according to the meta includes sent by the user.
24
- # +q+ is the model or partial AR query. If not set,
24
+ # `q` is the model or partial AR query. If not set,
25
25
  # action's model class is used instead.
26
26
  def with_includes(q = nil)
27
27
  q ||= self.class.model
@@ -179,14 +179,14 @@ END
179
179
  end
180
180
 
181
181
  {
182
- path_params: params.is_a?(Array) ? params : [params],
183
- resolved: true
182
+ path_params: params.is_a?(Array) ? params : [params],
183
+ resolved: true
184
184
  }
185
185
  end
186
186
 
187
187
  protected
188
- # Return representation of an associated resource +param+
189
- # with its instance in +val+.
188
+ # Return representation of an associated resource `param`
189
+ # with its instance in `val`.
190
190
  #
191
191
  # By default, it returns an unresolved resource, which contains
192
192
  # only object id and label. Resource will be resolved
@@ -204,11 +204,11 @@ END
204
204
  pass_includes = includes_pass_on_to(param.name)
205
205
 
206
206
  show = res_show.new(
207
- push_ins.request,
208
- push_ins.version,
209
- {},
210
- nil,
211
- @context
207
+ push_ins.request,
208
+ push_ins.version,
209
+ {},
210
+ nil,
211
+ @context
212
212
  )
213
213
  show.meta[:includes] = pass_includes
214
214
 
@@ -231,17 +231,17 @@ END
231
231
 
232
232
  else
233
233
  {
234
- param.value_id => val.send(res_output[param.value_id].db_name),
235
- param.value_label => val.send(res_output[param.value_label].db_name),
236
- _meta: {
237
- :path_params => args.is_a?(Array) ? args : [args],
238
- :resolved => false
239
- }
234
+ param.value_id => val.send(res_output[param.value_id].db_name),
235
+ param.value_label => val.send(res_output[param.value_label].db_name),
236
+ _meta: {
237
+ :path_params => args.is_a?(Array) ? args : [args],
238
+ :resolved => false
239
+ }
240
240
  }
241
241
  end
242
242
  end
243
243
 
244
- # Should an association with +name+ be resolved?
244
+ # Should an association with `name` be resolved?
245
245
  def includes_include?(name)
246
246
  includes = @context.action_instance.meta[:includes]
247
247
  return unless includes
@@ -324,7 +324,7 @@ END
324
324
 
325
325
  handle ::ActiveModel::Validations::ExclusionValidator do |v|
326
326
  opts = {
327
- values: v.options[:in].map { |v| v }
327
+ values: v.options[:in].map { |v| v }
328
328
  }
329
329
  opts[:message] = v.options[:message] if v.options[:message]
330
330
 
@@ -333,7 +333,7 @@ END
333
333
 
334
334
  handle ::ActiveModel::Validations::FormatValidator do |v|
335
335
  opts = {
336
- rx: v.options[:with]
336
+ rx: v.options[:with]
337
337
  }
338
338
  opts[:message] = v.options[:message] if v.options[:message]
339
339
 
@@ -342,7 +342,7 @@ END
342
342
 
343
343
  handle ::ActiveModel::Validations::InclusionValidator do |v|
344
344
  opts = {
345
- values: v.options[:in].map { |v| v }
345
+ values: v.options[:in].map { |v| v }
346
346
  }
347
347
  opts[:message] = v.options[:message] if v.options[:message]
348
348
 
@@ -49,10 +49,10 @@ module HaveAPI
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: status,
53
+ response: response,
54
+ message: message,
55
+ errors: errors
56
56
  })
57
57
  ret
58
58
  end
@@ -13,7 +13,7 @@ module HaveAPI::OutputFormatters
13
13
 
14
14
  def handle?(type)
15
15
  @types.detect do |t|
16
- File.fnmatch(type, t)
16
+ File.fnmatch(type, t)
17
17
  end
18
18
  end
19
19
  end
@@ -43,35 +43,35 @@ module HaveAPI::Parameters
43
43
 
44
44
  def describe(context)
45
45
  val_path = context.path_for(
46
- @resource::Show,
47
- context.endpoint && context.action_prepare && context.layout == :object && context.call_path_params(context.action, context.action_prepare)
46
+ @resource::Show,
47
+ context.endpoint && context.action_prepare && context.layout == :object && context.call_path_params(context.action, context.action_prepare)
48
48
  )
49
49
  val_method = @resource::Index.http_method.to_s.upcase
50
50
 
51
51
  choices_path = context.path_for(
52
- @choices,
53
- context.endpoint && context.layout == :object && context.call_path_params(context.action, context.action_prepare)
52
+ @choices,
53
+ context.endpoint && context.layout == :object && context.call_path_params(context.action, context.action_prepare)
54
54
  )
55
55
  choices_method = @choices.http_method.to_s.upcase
56
56
 
57
57
  {
58
- required: required?,
59
- label: @label,
60
- description: @desc,
61
- type: 'Resource',
62
- resource: @resource_path,
63
- value_id: @value_id,
64
- value_label: @value_label,
65
- value: context.action_prepare && {
66
- path: val_path,
67
- method: val_method,
68
- help: "#{val_path}?method=#{val_method}",
69
- },
70
- choices: {
71
- path: choices_path,
72
- method: choices_method,
73
- help: "#{choices_path}?method=#{choices_method}"
74
- }
58
+ required: required?,
59
+ label: @label,
60
+ description: @desc,
61
+ type: 'Resource',
62
+ resource: @resource_path,
63
+ value_id: @value_id,
64
+ value_label: @value_label,
65
+ value: context.action_prepare && {
66
+ path: val_path,
67
+ method: val_method,
68
+ help: "#{val_path}?method=#{val_method}",
69
+ },
70
+ choices: {
71
+ path: choices_path,
72
+ method: choices_method,
73
+ help: "#{choices_path}?method=#{choices_method}"
74
+ }
75
75
  }
76
76
  end
77
77
 
@@ -93,7 +93,7 @@ module HaveAPI::Parameters
93
93
 
94
94
  def clean(raw)
95
95
  ::HaveAPI::ModelAdapter.for(
96
- show_action.input.layout, @resource.model
96
+ show_action.input.layout, @resource.model
97
97
  ).input_clean(@resource.model, raw, @extra)
98
98
  end
99
99
 
@@ -46,13 +46,13 @@ module HaveAPI::Parameters
46
46
 
47
47
  def describe(context)
48
48
  {
49
- required: required?,
50
- label: @label,
51
- description: @desc,
52
- type: @type ? @type.to_s : String.to_s,
53
- validators: @validators ? @validators.describe : {},
54
- default: @default,
55
- protected: @protected || false,
49
+ required: required?,
50
+ label: @label,
51
+ description: @desc,
52
+ type: @type ? @type.to_s : String.to_s,
53
+ validators: @validators ? @validators.describe : {},
54
+ default: @default,
55
+ protected: @protected || false,
56
56
  }
57
57
  end
58
58