apia 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/VERSION +1 -0
- data/lib/apia.rb +21 -0
- data/lib/apia/api.rb +100 -0
- data/lib/apia/argument_set.rb +221 -0
- data/lib/apia/authenticator.rb +57 -0
- data/lib/apia/callable_with_environment.rb +43 -0
- data/lib/apia/controller.rb +32 -0
- data/lib/apia/defineable.rb +60 -0
- data/lib/apia/definition.rb +27 -0
- data/lib/apia/definitions/api.rb +51 -0
- data/lib/apia/definitions/argument.rb +77 -0
- data/lib/apia/definitions/argument_set.rb +33 -0
- data/lib/apia/definitions/authenticator.rb +46 -0
- data/lib/apia/definitions/controller.rb +41 -0
- data/lib/apia/definitions/endpoint.rb +74 -0
- data/lib/apia/definitions/enum.rb +31 -0
- data/lib/apia/definitions/error.rb +59 -0
- data/lib/apia/definitions/field.rb +117 -0
- data/lib/apia/definitions/lookup_argument_set.rb +27 -0
- data/lib/apia/definitions/object.rb +29 -0
- data/lib/apia/definitions/polymorph.rb +29 -0
- data/lib/apia/definitions/polymorph_option.rb +53 -0
- data/lib/apia/definitions/scalar.rb +23 -0
- data/lib/apia/definitions/type.rb +109 -0
- data/lib/apia/dsl.rb +23 -0
- data/lib/apia/dsls/api.rb +37 -0
- data/lib/apia/dsls/argument.rb +27 -0
- data/lib/apia/dsls/argument_set.rb +35 -0
- data/lib/apia/dsls/authenticator.rb +38 -0
- data/lib/apia/dsls/concerns/has_fields.rb +38 -0
- data/lib/apia/dsls/controller.rb +34 -0
- data/lib/apia/dsls/endpoint.rb +79 -0
- data/lib/apia/dsls/enum.rb +19 -0
- data/lib/apia/dsls/error.rb +26 -0
- data/lib/apia/dsls/field.rb +27 -0
- data/lib/apia/dsls/lookup_argument_set.rb +24 -0
- data/lib/apia/dsls/object.rb +19 -0
- data/lib/apia/dsls/polymorph.rb +19 -0
- data/lib/apia/dsls/route_group.rb +43 -0
- data/lib/apia/dsls/route_set.rb +40 -0
- data/lib/apia/dsls/scalar.rb +23 -0
- data/lib/apia/dsls/scope_descriptions.rb +17 -0
- data/lib/apia/endpoint.rb +110 -0
- data/lib/apia/enum.rb +43 -0
- data/lib/apia/environment_error_handling.rb +74 -0
- data/lib/apia/error.rb +61 -0
- data/lib/apia/error_set.rb +15 -0
- data/lib/apia/errors/error_exception_error.rb +32 -0
- data/lib/apia/errors/field_spec_parse_error.rb +23 -0
- data/lib/apia/errors/invalid_argument_error.rb +68 -0
- data/lib/apia/errors/invalid_enum_option_error.rb +21 -0
- data/lib/apia/errors/invalid_helper_error.rb +6 -0
- data/lib/apia/errors/invalid_json_error.rb +23 -0
- data/lib/apia/errors/invalid_polymorph_value_error.rb +21 -0
- data/lib/apia/errors/invalid_scalar_value_error.rb +21 -0
- data/lib/apia/errors/manifest_error.rb +43 -0
- data/lib/apia/errors/missing_argument_error.rb +40 -0
- data/lib/apia/errors/null_field_value_error.rb +37 -0
- data/lib/apia/errors/parse_error.rb +10 -0
- data/lib/apia/errors/runtime_error.rb +30 -0
- data/lib/apia/errors/scope_not_granted_error.rb +15 -0
- data/lib/apia/errors/standard_error.rb +6 -0
- data/lib/apia/field_set.rb +76 -0
- data/lib/apia/field_spec.rb +155 -0
- data/lib/apia/helpers.rb +34 -0
- data/lib/apia/hook_set.rb +30 -0
- data/lib/apia/lookup_argument_set.rb +57 -0
- data/lib/apia/lookup_environment.rb +27 -0
- data/lib/apia/manifest_errors.rb +62 -0
- data/lib/apia/mock_request.rb +18 -0
- data/lib/apia/object.rb +68 -0
- data/lib/apia/object_set.rb +21 -0
- data/lib/apia/pagination_object.rb +34 -0
- data/lib/apia/polymorph.rb +50 -0
- data/lib/apia/rack.rb +184 -0
- data/lib/apia/rack_error.rb +17 -0
- data/lib/apia/request.rb +67 -0
- data/lib/apia/request_environment.rb +84 -0
- data/lib/apia/request_headers.rb +42 -0
- data/lib/apia/response.rb +64 -0
- data/lib/apia/route.rb +61 -0
- data/lib/apia/route_group.rb +20 -0
- data/lib/apia/route_set.rb +89 -0
- data/lib/apia/scalar.rb +52 -0
- data/lib/apia/scalars.rb +25 -0
- data/lib/apia/scalars/base64.rb +31 -0
- data/lib/apia/scalars/boolean.rb +37 -0
- data/lib/apia/scalars/date.rb +45 -0
- data/lib/apia/scalars/decimal.rb +36 -0
- data/lib/apia/scalars/integer.rb +34 -0
- data/lib/apia/scalars/string.rb +24 -0
- data/lib/apia/scalars/unix_time.rb +40 -0
- data/lib/apia/schema/api_controller_schema_type.rb +17 -0
- data/lib/apia/schema/api_schema_type.rb +43 -0
- data/lib/apia/schema/argument_schema_type.rb +28 -0
- data/lib/apia/schema/argument_set_schema_type.rb +21 -0
- data/lib/apia/schema/authenticator_schema_type.rb +22 -0
- data/lib/apia/schema/controller.rb +39 -0
- data/lib/apia/schema/controller_endpoint_schema_type.rb +17 -0
- data/lib/apia/schema/controller_schema_type.rb +32 -0
- data/lib/apia/schema/endpoint_schema_type.rb +35 -0
- data/lib/apia/schema/enum_schema_type.rb +20 -0
- data/lib/apia/schema/enum_value_schema_type.rb +14 -0
- data/lib/apia/schema/error_schema_type.rb +23 -0
- data/lib/apia/schema/field_schema_type.rb +38 -0
- data/lib/apia/schema/field_spec_options_schema_type.rb +16 -0
- data/lib/apia/schema/lookup_argument_set_schema_type.rb +25 -0
- data/lib/apia/schema/object_schema_polymorph.rb +31 -0
- data/lib/apia/schema/object_schema_type.rb +21 -0
- data/lib/apia/schema/polymorph_option_schema_type.rb +16 -0
- data/lib/apia/schema/polymorph_schema_type.rb +20 -0
- data/lib/apia/schema/request_method_enum.rb +21 -0
- data/lib/apia/schema/route_group_schema_type.rb +19 -0
- data/lib/apia/schema/route_schema_type.rb +31 -0
- data/lib/apia/schema/route_set_schema_type.rb +20 -0
- data/lib/apia/schema/scalar_schema_type.rb +15 -0
- data/lib/apia/schema/scope_type.rb +14 -0
- data/lib/apia/version.rb +12 -0
- metadata +188 -0
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'apia/errors/runtime_error'
|
4
|
+
|
5
|
+
module Apia
|
6
|
+
# This is the error exception that must be raised when you wish to raise an
|
7
|
+
# error. It should be initialized with the Apia::Error class that you wish
|
8
|
+
# to raise.
|
9
|
+
class ErrorExceptionError < Apia::RuntimeError
|
10
|
+
|
11
|
+
attr_reader :error_class
|
12
|
+
attr_reader :fields
|
13
|
+
|
14
|
+
def initialize(error_class, fields = {})
|
15
|
+
@error_class = error_class
|
16
|
+
@fields = fields
|
17
|
+
end
|
18
|
+
|
19
|
+
def http_status
|
20
|
+
@error_class.definition.http_status || 500
|
21
|
+
end
|
22
|
+
|
23
|
+
def hash
|
24
|
+
{
|
25
|
+
code: @error_class.definition.code,
|
26
|
+
description: @error_class.definition.description,
|
27
|
+
detail: @error_class.definition.fields.generate_hash(@fields)
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'apia/errors/runtime_error'
|
4
|
+
|
5
|
+
module Apia
|
6
|
+
class FieldSpecParseError < Apia::RuntimeError
|
7
|
+
|
8
|
+
def http_status
|
9
|
+
400
|
10
|
+
end
|
11
|
+
|
12
|
+
def hash
|
13
|
+
{
|
14
|
+
code: 'invalid_field_spec',
|
15
|
+
description: 'The field spec string was invalid',
|
16
|
+
detail: {
|
17
|
+
details: message
|
18
|
+
}
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'apia/errors/runtime_error'
|
4
|
+
|
5
|
+
module Apia
|
6
|
+
# Raised when an argument set cannot be created based on the source object that
|
7
|
+
# has been provided. For example, if a validation rule exists or a scalar cannot
|
8
|
+
# be parsed for the underlying object.
|
9
|
+
#
|
10
|
+
# This is not raised for MISSING argument errors.
|
11
|
+
class InvalidArgumentError < Apia::RuntimeError
|
12
|
+
|
13
|
+
ISSUE_DESCRIPTIONS = {
|
14
|
+
invalid_scalar: 'The value provided was not of an appropriate type for the scalar that was requested. For example, you may have passed a string where an integer was required etc...',
|
15
|
+
parse_error: 'The value provided could not be parsed into an appropriate value by the server. For example, if a date was expected and the value could not be interpretted as such.',
|
16
|
+
validation_error: 'A validation rule that has been specified for this argument was not satisfied. See the further details in the response and in the documentation.',
|
17
|
+
invalid_enum_value: 'The value provided was not one of the options suitable for the enum.',
|
18
|
+
missing_lookup_value: 'A value for a lookup argument set has not been provided but at least one value is required.',
|
19
|
+
ambiguous_lookup_values: 'More than one value has been provided for a lookup argument set. Only one option may be provided.'
|
20
|
+
}.freeze
|
21
|
+
|
22
|
+
attr_reader :argument
|
23
|
+
attr_reader :index
|
24
|
+
attr_reader :path
|
25
|
+
attr_reader :errors
|
26
|
+
attr_reader :issue
|
27
|
+
|
28
|
+
def initialize(argument, issue: nil, index: nil, path: [], errors: [])
|
29
|
+
@argument = argument
|
30
|
+
@index = index
|
31
|
+
@path = path
|
32
|
+
@issue = issue
|
33
|
+
@errors = errors
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_s
|
37
|
+
@issue.to_s
|
38
|
+
end
|
39
|
+
|
40
|
+
def http_status
|
41
|
+
400
|
42
|
+
end
|
43
|
+
|
44
|
+
def path_string
|
45
|
+
@path.map(&:name).join('.')
|
46
|
+
end
|
47
|
+
|
48
|
+
def hash
|
49
|
+
{
|
50
|
+
code: 'invalid_argument',
|
51
|
+
description: "The '#{path_string}' argument is invalid",
|
52
|
+
detail: {
|
53
|
+
path: @path.map(&:name),
|
54
|
+
index: @index,
|
55
|
+
issue: @issue&.to_s,
|
56
|
+
issue_description: ISSUE_DESCRIPTIONS[@issue.to_sym],
|
57
|
+
errors: @errors,
|
58
|
+
argument: {
|
59
|
+
id: argument.id,
|
60
|
+
name: argument.name,
|
61
|
+
description: argument.description
|
62
|
+
}
|
63
|
+
}
|
64
|
+
}
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'apia/errors/runtime_error'
|
4
|
+
|
5
|
+
module Apia
|
6
|
+
class InvalidEnumOptionError < Apia::RuntimeError
|
7
|
+
|
8
|
+
attr_reader :enum
|
9
|
+
attr_reader :given_value
|
10
|
+
|
11
|
+
def initialize(enum, given_value)
|
12
|
+
@enum = enum
|
13
|
+
@given_value = given_value
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_s
|
17
|
+
"Invalid option for `#{enum.class.definition.name || 'AnonymousEnum'}` (got: #{@given_value.inspect} (#{@given_value.class}))"
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'apia/errors/runtime_error'
|
4
|
+
|
5
|
+
module Apia
|
6
|
+
class InvalidJSONError < Apia::RuntimeError
|
7
|
+
|
8
|
+
def http_status
|
9
|
+
400
|
10
|
+
end
|
11
|
+
|
12
|
+
def hash
|
13
|
+
{
|
14
|
+
code: 'invalid_json_body',
|
15
|
+
description: 'The JSON body provided with this request is invalid',
|
16
|
+
detail: {
|
17
|
+
details: message
|
18
|
+
}
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'apia/errors/runtime_error'
|
4
|
+
|
5
|
+
module Apia
|
6
|
+
class InvalidPolymorphValueError < Apia::RuntimeError
|
7
|
+
|
8
|
+
attr_reader :polymorph
|
9
|
+
attr_reader :given_value
|
10
|
+
|
11
|
+
def initialize(polymorph, given_value)
|
12
|
+
@polymorph = polymorph
|
13
|
+
@given_value = given_value
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_s
|
17
|
+
"Invalid value for `#{polymorph.definition.id}` (got: #{@given_value.inspect})"
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'apia/errors/runtime_error'
|
4
|
+
|
5
|
+
module Apia
|
6
|
+
class InvalidScalarValueError < Apia::RuntimeError
|
7
|
+
|
8
|
+
attr_reader :scalar
|
9
|
+
attr_reader :given_value
|
10
|
+
|
11
|
+
def initialize(scalar, given_value)
|
12
|
+
@scalar = scalar
|
13
|
+
@given_value = given_value
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_s
|
17
|
+
"Invalid value for `#{scalar.name}` (got: #{@given_value.inspect} (#{@given_value.class}))"
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'apia/rack'
|
4
|
+
|
5
|
+
module Apia
|
6
|
+
class ManifestError < StandardError
|
7
|
+
|
8
|
+
def initialize(errors)
|
9
|
+
@errors = errors
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_s
|
13
|
+
"#{@errors.errors.size} object(s) have issues that need attention (#{errors})"
|
14
|
+
end
|
15
|
+
|
16
|
+
def errors
|
17
|
+
@errors.errors.each_with_object([]) do |(object, errors), array|
|
18
|
+
errors.each do |error|
|
19
|
+
array << "#{object.id}: #{error[:code]} (#{error[:message]})"
|
20
|
+
end
|
21
|
+
end.join(', ')
|
22
|
+
end
|
23
|
+
|
24
|
+
def detail
|
25
|
+
@errors.errors.map do |object, errors|
|
26
|
+
{
|
27
|
+
object: object.id,
|
28
|
+
errors: errors.map do |error|
|
29
|
+
{
|
30
|
+
code: error[:code],
|
31
|
+
description: error[:message]
|
32
|
+
}
|
33
|
+
end
|
34
|
+
}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def triplet
|
39
|
+
Rack.error_triplet('manifest_error', description: 'An issue exists with the API manifest that needs resolving by the developer.', detail: detail)
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'apia/errors/runtime_error'
|
4
|
+
|
5
|
+
module Apia
|
6
|
+
# This is raised when an argument set cannot be created because an argument
|
7
|
+
# that was required is not present on the source object.
|
8
|
+
class MissingArgumentError < Apia::RuntimeError
|
9
|
+
|
10
|
+
attr_reader :argument
|
11
|
+
|
12
|
+
def initialize(argument, path: [])
|
13
|
+
@argument = argument
|
14
|
+
@path = path
|
15
|
+
end
|
16
|
+
|
17
|
+
def http_status
|
18
|
+
400
|
19
|
+
end
|
20
|
+
|
21
|
+
def path_string
|
22
|
+
@path.map(&:name).join('.')
|
23
|
+
end
|
24
|
+
|
25
|
+
def hash
|
26
|
+
{
|
27
|
+
code: 'missing_required_argument',
|
28
|
+
description: "The '#{path_string}' argument is required but has not been provided",
|
29
|
+
detail: {
|
30
|
+
path: @path.map(&:name),
|
31
|
+
argument: {
|
32
|
+
name: argument.name,
|
33
|
+
description: argument.description
|
34
|
+
}
|
35
|
+
}
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'apia/errors/runtime_error'
|
4
|
+
|
5
|
+
module Apia
|
6
|
+
class NullFieldValueError < Apia::RuntimeError
|
7
|
+
|
8
|
+
attr_reader :field
|
9
|
+
|
10
|
+
def initialize(field, source)
|
11
|
+
@field = field
|
12
|
+
@source = source
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s
|
16
|
+
"Value for `#{field.name}` is null (but cannot be)"
|
17
|
+
end
|
18
|
+
|
19
|
+
def http_status
|
20
|
+
500
|
21
|
+
end
|
22
|
+
|
23
|
+
def hash
|
24
|
+
{
|
25
|
+
code: 'null_value_for_non_null_field',
|
26
|
+
description: to_s,
|
27
|
+
detail: {
|
28
|
+
field: {
|
29
|
+
id: @field.id,
|
30
|
+
name: @field.name
|
31
|
+
}
|
32
|
+
}
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'apia/errors/runtime_error'
|
4
|
+
|
5
|
+
module Apia
|
6
|
+
# A parse error is raised when we are unable to parse input provided by an
|
7
|
+
# API consumer to turn it into an appropriate Scalar or Type.
|
8
|
+
class ParseError < Apia::RuntimeError
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Apia
|
4
|
+
# Runtime errors occurr during API requests because they could not
|
5
|
+
# be detected before an action is processed.
|
6
|
+
class RuntimeError < StandardError
|
7
|
+
|
8
|
+
# Return the default HTTP status code that should be returned when this
|
9
|
+
# error is encoutered over HTTP
|
10
|
+
#
|
11
|
+
# @return [Integer]
|
12
|
+
def http_status
|
13
|
+
400
|
14
|
+
end
|
15
|
+
|
16
|
+
# Return the hash that describes this error
|
17
|
+
#
|
18
|
+
# @return [Hash]
|
19
|
+
def hash
|
20
|
+
{
|
21
|
+
code: 'generic_runtime_error',
|
22
|
+
description: message,
|
23
|
+
detail: {
|
24
|
+
class: self.class.name
|
25
|
+
}
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'apia/error'
|
4
|
+
|
5
|
+
module Apia
|
6
|
+
class ScopeNotGrantedError < Apia::Error
|
7
|
+
|
8
|
+
code :scope_not_granted
|
9
|
+
http_status 403
|
10
|
+
description 'The scope required for this endpoint has not been granted to the authenticating identity'
|
11
|
+
|
12
|
+
field :scopes, [:string]
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'apia/helpers'
|
4
|
+
require 'apia/scalar'
|
5
|
+
require 'apia/object'
|
6
|
+
require 'apia/enum'
|
7
|
+
require 'apia/field_spec'
|
8
|
+
|
9
|
+
module Apia
|
10
|
+
class FieldSet < Hash
|
11
|
+
|
12
|
+
# Add a new field to the fieldset
|
13
|
+
#
|
14
|
+
# @param field [Apia::Field]
|
15
|
+
# @return [Apia::Field]
|
16
|
+
def add(field)
|
17
|
+
self[field.name] = field
|
18
|
+
end
|
19
|
+
|
20
|
+
# Validate this field set and add errors as appropriate
|
21
|
+
#
|
22
|
+
# @param errors [Apia::ManifestErrors]
|
23
|
+
# @param object [Object]
|
24
|
+
# @return [void]
|
25
|
+
def validate(errors, object)
|
26
|
+
each_value do |field|
|
27
|
+
unless field.type.usable_for_field?
|
28
|
+
errors.add object, 'InvalidFieldType', "Type for field #{field.name} must be a scalar, enum or object"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Generate a hash for the fields that are defined on this object.
|
34
|
+
# It should receive the source object as well as a request
|
35
|
+
#
|
36
|
+
# @param source [Object, Hash]
|
37
|
+
# @param request [Apia::Request]
|
38
|
+
# @param only [Array]
|
39
|
+
# @return [Hash]
|
40
|
+
def generate_hash(source, request: nil, path: [])
|
41
|
+
each_with_object({}) do |(_, field), hash|
|
42
|
+
next unless field.include?(source, request)
|
43
|
+
|
44
|
+
field_path = path + [field]
|
45
|
+
next if request&.endpoint && !request&.endpoint&.include_field?(field_path)
|
46
|
+
|
47
|
+
value = field.value(source, request: request, path: field_path)
|
48
|
+
next if value == :skip
|
49
|
+
|
50
|
+
hash[field.name.to_sym] = value
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Generate a default field spec for this field set based on the values
|
55
|
+
# provided for the include option.
|
56
|
+
#
|
57
|
+
# @return [FieldSpec]
|
58
|
+
def spec
|
59
|
+
@spec ||= begin
|
60
|
+
spec = each_with_object([]) do |(key, field), array|
|
61
|
+
next if field.include == false
|
62
|
+
|
63
|
+
if field.include.is_a?(::String)
|
64
|
+
array << "#{key}[#{field.include}]"
|
65
|
+
elsif field.type.object? || field.type.polymorph?
|
66
|
+
array << "#{key}[*]"
|
67
|
+
else
|
68
|
+
array << key
|
69
|
+
end
|
70
|
+
end.join(',')
|
71
|
+
FieldSpec.parse(spec)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|