treaty 0.7.0 → 0.8.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.
- checksums.yaml +4 -4
- data/README.md +5 -0
- data/config/locales/en.yml +3 -0
- data/lib/treaty/attribute/base.rb +13 -5
- data/lib/treaty/attribute/dsl.rb +90 -0
- data/lib/treaty/attribute/entity/attribute.rb +25 -0
- data/lib/treaty/attribute/entity/builder.rb +23 -0
- data/lib/treaty/attribute/option/base.rb +17 -1
- data/lib/treaty/attribute/option/modifiers/as_modifier.rb +5 -3
- data/lib/treaty/attribute/option/validators/inclusion_validator.rb +20 -8
- data/lib/treaty/attribute/option/validators/required_validator.rb +8 -2
- data/lib/treaty/attribute/option/validators/type_validator.rb +51 -40
- data/lib/treaty/attribute/option_orchestrator.rb +7 -5
- data/lib/treaty/attribute/validation/nested_array_validator.rb +18 -12
- data/lib/treaty/attribute/validation/nested_transformer.rb +18 -12
- data/lib/treaty/base.rb +1 -1
- data/lib/treaty/controller/dsl.rb +4 -1
- data/lib/treaty/entity.rb +84 -0
- data/lib/treaty/info/entity/builder.rb +50 -0
- data/lib/treaty/info/entity/dsl.rb +28 -0
- data/lib/treaty/info/entity/result.rb +15 -0
- data/lib/treaty/info/rest/builder.rb +110 -0
- data/lib/treaty/info/rest/dsl.rb +28 -0
- data/lib/treaty/info/rest/result.rb +15 -0
- data/lib/treaty/request/attribute/attribute.rb +1 -0
- data/lib/treaty/request/attribute/builder.rb +1 -0
- data/lib/treaty/request/entity.rb +33 -0
- data/lib/treaty/request/factory.rb +61 -14
- data/lib/treaty/request/validator.rb +65 -0
- data/lib/treaty/response/attribute/attribute.rb +1 -0
- data/lib/treaty/response/attribute/builder.rb +1 -0
- data/lib/treaty/response/entity.rb +33 -0
- data/lib/treaty/response/factory.rb +61 -14
- data/lib/treaty/response/validator.rb +57 -0
- data/lib/treaty/version.rb +1 -1
- data/lib/treaty/versions/execution/request.rb +10 -5
- data/lib/treaty/versions/factory.rb +16 -5
- data/lib/treaty/versions/resolver.rb +8 -2
- data/lib/treaty/versions/workspace.rb +2 -2
- metadata +15 -8
- data/lib/treaty/info/builder.rb +0 -108
- data/lib/treaty/info/dsl.rb +0 -26
- data/lib/treaty/info/result.rb +0 -13
- data/lib/treaty/request/attribute/validation/orchestrator.rb +0 -19
- data/lib/treaty/request/attribute/validator.rb +0 -50
- data/lib/treaty/response/attribute/validation/orchestrator.rb +0 -19
- data/lib/treaty/response/attribute/validator.rb +0 -44
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Treaty
|
|
4
|
+
# Base class for defining DTO (Data Transfer Object) entities in Treaty.
|
|
5
|
+
#
|
|
6
|
+
# ## Purpose
|
|
7
|
+
#
|
|
8
|
+
# Treaty::Entity provides a base class for creating reusable DTO classes
|
|
9
|
+
# that can be used in both request and response definitions. This allows
|
|
10
|
+
# for better code organization and reusability of common data structures.
|
|
11
|
+
#
|
|
12
|
+
# ## Usage
|
|
13
|
+
#
|
|
14
|
+
# Create a DTO class by inheriting from Treaty::Entity:
|
|
15
|
+
#
|
|
16
|
+
# ```ruby
|
|
17
|
+
# class PostEntity < Treaty::Entity
|
|
18
|
+
# string :id
|
|
19
|
+
# string :title
|
|
20
|
+
# string :content
|
|
21
|
+
# datetime :created_at
|
|
22
|
+
# end
|
|
23
|
+
# ```
|
|
24
|
+
#
|
|
25
|
+
# Then use it in your treaty definitions:
|
|
26
|
+
#
|
|
27
|
+
# ```ruby
|
|
28
|
+
# class CreateTreaty < ApplicationTreaty
|
|
29
|
+
# version 1 do
|
|
30
|
+
# request PostEntity
|
|
31
|
+
# response 201, PostEntity
|
|
32
|
+
# end
|
|
33
|
+
# end
|
|
34
|
+
# ```
|
|
35
|
+
#
|
|
36
|
+
# ## Attribute Defaults
|
|
37
|
+
#
|
|
38
|
+
# Unlike request/response blocks, Entity attributes are required by default:
|
|
39
|
+
# - All attributes have `required: true` unless explicitly marked as `:optional`
|
|
40
|
+
# - Use `:optional` helper to make attributes optional:
|
|
41
|
+
# ```ruby
|
|
42
|
+
# string :title # required by default
|
|
43
|
+
# string :summary, :optional # optional
|
|
44
|
+
# ```
|
|
45
|
+
#
|
|
46
|
+
# ## Features
|
|
47
|
+
#
|
|
48
|
+
# - **Type Safety** - Enforce strict type checking for all attributes
|
|
49
|
+
# - **Nested Structures** - Support for nested objects and arrays
|
|
50
|
+
# - **Validation** - Built-in validation for all attribute types
|
|
51
|
+
# - **Reusability** - Define once, use in multiple treaties
|
|
52
|
+
# - **Options** - Full support for attribute options (required, default, as, etc.)
|
|
53
|
+
#
|
|
54
|
+
# ## Supported Types
|
|
55
|
+
#
|
|
56
|
+
# - `string` - String values
|
|
57
|
+
# - `integer` - Integer values
|
|
58
|
+
# - `boolean` - Boolean values (true/false)
|
|
59
|
+
# - `datetime` - DateTime values
|
|
60
|
+
# - `array` - Array values (with nested type definition)
|
|
61
|
+
# - `object` - Object values (with nested attributes)
|
|
62
|
+
class Entity
|
|
63
|
+
include Info::Entity::DSL
|
|
64
|
+
include Attribute::DSL
|
|
65
|
+
|
|
66
|
+
class << self
|
|
67
|
+
private
|
|
68
|
+
|
|
69
|
+
# Creates an Attribute::Entity::Attribute for this Entity class
|
|
70
|
+
#
|
|
71
|
+
# @return [Attribute::Entity::Attribute] Created attribute instance
|
|
72
|
+
def create_attribute(name, type, *helpers, nesting_level:, **options, &block)
|
|
73
|
+
Attribute::Entity::Attribute.new(
|
|
74
|
+
name,
|
|
75
|
+
type,
|
|
76
|
+
*helpers,
|
|
77
|
+
nesting_level:,
|
|
78
|
+
**options,
|
|
79
|
+
&block
|
|
80
|
+
)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Treaty
|
|
4
|
+
module Info
|
|
5
|
+
module Entity
|
|
6
|
+
class Builder
|
|
7
|
+
attr_reader :attributes
|
|
8
|
+
|
|
9
|
+
def self.build(...)
|
|
10
|
+
new.build(...)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def build(collection_of_attributes:)
|
|
14
|
+
build_all(
|
|
15
|
+
attributes: collection_of_attributes
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
self
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def build_all(attributes:)
|
|
24
|
+
@attributes = build_versions_with(attributes)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
##########################################################################
|
|
28
|
+
|
|
29
|
+
def build_versions_with(collection, current_level = 0)
|
|
30
|
+
collection.to_h do |attribute|
|
|
31
|
+
[
|
|
32
|
+
attribute.name,
|
|
33
|
+
{
|
|
34
|
+
type: attribute.type,
|
|
35
|
+
options: attribute.options,
|
|
36
|
+
attributes: build_nested_attributes(attribute, current_level)
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def build_nested_attributes(attribute, current_level)
|
|
43
|
+
return {} unless attribute.nested?
|
|
44
|
+
|
|
45
|
+
build_versions_with(attribute.collection_of_attributes, current_level + 1)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Treaty
|
|
4
|
+
module Info
|
|
5
|
+
module Entity
|
|
6
|
+
module DSL
|
|
7
|
+
def self.included(base)
|
|
8
|
+
base.extend(ClassMethods)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
module ClassMethods
|
|
12
|
+
def info
|
|
13
|
+
builder = Builder.build(
|
|
14
|
+
collection_of_attributes:
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
Result.new(builder)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# API: Treaty Web
|
|
21
|
+
def treaty?
|
|
22
|
+
true
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Treaty
|
|
4
|
+
module Info
|
|
5
|
+
module Rest
|
|
6
|
+
class Builder
|
|
7
|
+
attr_reader :versions
|
|
8
|
+
|
|
9
|
+
def self.build(...)
|
|
10
|
+
new.build(...)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def build(collection_of_versions:)
|
|
14
|
+
build_all(
|
|
15
|
+
versions: collection_of_versions
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
self
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def build_all(versions:)
|
|
24
|
+
build_versions_with(
|
|
25
|
+
collection: versions
|
|
26
|
+
)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
##########################################################################
|
|
30
|
+
|
|
31
|
+
def build_versions_with(collection:) # rubocop:disable Metrics/MethodLength
|
|
32
|
+
@versions = collection.map do |version|
|
|
33
|
+
gem_version = version.version.version
|
|
34
|
+
{
|
|
35
|
+
version: gem_version.version,
|
|
36
|
+
segments: gem_version.segments,
|
|
37
|
+
default: version.default_result,
|
|
38
|
+
summary: version.summary_text,
|
|
39
|
+
strategy: version.strategy_instance.code,
|
|
40
|
+
deprecated: version.deprecated_result,
|
|
41
|
+
executor: build_executor_with(version),
|
|
42
|
+
request: build_request_with(version),
|
|
43
|
+
response: build_response_with(version)
|
|
44
|
+
}
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
##########################################################################
|
|
49
|
+
|
|
50
|
+
def build_executor_with(version)
|
|
51
|
+
{
|
|
52
|
+
executor: version.executor.executor,
|
|
53
|
+
method: version.executor.method
|
|
54
|
+
}
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
##########################################################################
|
|
58
|
+
|
|
59
|
+
def build_request_with(version)
|
|
60
|
+
build_attributes_structure(version.request_factory)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def build_response_with(version)
|
|
64
|
+
response_factory = version.response_factory
|
|
65
|
+
{
|
|
66
|
+
status: response_factory.status
|
|
67
|
+
}.merge(build_attributes_structure(response_factory))
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
##########################################################################
|
|
71
|
+
|
|
72
|
+
def build_attributes_structure(factory)
|
|
73
|
+
{
|
|
74
|
+
attributes: build_attributes_hash(factory.collection_of_attributes)
|
|
75
|
+
}
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def build_attributes_hash(collection, current_level = 0)
|
|
79
|
+
# validate_nesting_level!(current_level)
|
|
80
|
+
|
|
81
|
+
collection.to_h do |attribute|
|
|
82
|
+
[
|
|
83
|
+
attribute.name,
|
|
84
|
+
{
|
|
85
|
+
type: attribute.type,
|
|
86
|
+
options: attribute.options,
|
|
87
|
+
attributes: build_nested_attributes(attribute, current_level)
|
|
88
|
+
}
|
|
89
|
+
]
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def build_nested_attributes(attribute, current_level)
|
|
94
|
+
return {} unless attribute.nested?
|
|
95
|
+
|
|
96
|
+
build_attributes_hash(attribute.collection_of_attributes, current_level + 1)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# def validate_nesting_level!(level)
|
|
100
|
+
# return unless level > Treaty::Engine.config.treaty.attribute_nesting_level
|
|
101
|
+
#
|
|
102
|
+
# raise Treaty::Exceptions::NestedAttributes,
|
|
103
|
+
# I18n.t("treaty.attributes.errors.nesting_level_exceeded",
|
|
104
|
+
# level:,
|
|
105
|
+
# max_level: Treaty::Engine.config.treaty.attribute_nesting_level)
|
|
106
|
+
# end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Treaty
|
|
4
|
+
module Info
|
|
5
|
+
module Rest
|
|
6
|
+
module DSL
|
|
7
|
+
def self.included(base)
|
|
8
|
+
base.extend(ClassMethods)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
module ClassMethods
|
|
12
|
+
def info
|
|
13
|
+
builder = Builder.build(
|
|
14
|
+
collection_of_versions:
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
Result.new(builder)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# API: Treaty Web
|
|
21
|
+
def treaty?
|
|
22
|
+
true
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Treaty
|
|
4
|
+
module Request
|
|
5
|
+
# Entity class for request definitions.
|
|
6
|
+
# Attributes are required by default.
|
|
7
|
+
#
|
|
8
|
+
# This class is used internally when defining request blocks.
|
|
9
|
+
# When you write a request block, Treaty creates an anonymous
|
|
10
|
+
# class based on Request::Entity.
|
|
11
|
+
class Entity
|
|
12
|
+
include Treaty::Attribute::DSL
|
|
13
|
+
|
|
14
|
+
class << self
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
# Creates a Request::Attribute::Attribute for this Request::Entity class
|
|
18
|
+
#
|
|
19
|
+
# @return [Request::Attribute::Attribute] Created attribute instance
|
|
20
|
+
def create_attribute(name, type, *helpers, nesting_level:, **options, &block)
|
|
21
|
+
Attribute::Attribute.new(
|
|
22
|
+
name,
|
|
23
|
+
type,
|
|
24
|
+
*helpers,
|
|
25
|
+
nesting_level:,
|
|
26
|
+
**options,
|
|
27
|
+
&block
|
|
28
|
+
)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -2,33 +2,80 @@
|
|
|
2
2
|
|
|
3
3
|
module Treaty
|
|
4
4
|
module Request
|
|
5
|
+
# Factory for creating request definitions.
|
|
6
|
+
#
|
|
7
|
+
# Supports two modes:
|
|
8
|
+
# 1. Block mode: Creates an anonymous Request::Entity class with the block
|
|
9
|
+
# 2. Entity mode: Uses a provided Entity class directly
|
|
10
|
+
#
|
|
11
|
+
# ## Block Mode
|
|
12
|
+
#
|
|
13
|
+
# ```ruby
|
|
14
|
+
# request do
|
|
15
|
+
# object :post do
|
|
16
|
+
# string :title
|
|
17
|
+
# end
|
|
18
|
+
# end
|
|
19
|
+
# ```
|
|
20
|
+
#
|
|
21
|
+
# ## Entity Mode
|
|
22
|
+
#
|
|
23
|
+
# ```ruby
|
|
24
|
+
# request PostRequestEntity
|
|
25
|
+
# ```
|
|
5
26
|
class Factory
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
)
|
|
27
|
+
# Uses a provided Entity class
|
|
28
|
+
#
|
|
29
|
+
# @param entity_class [Class] Entity class to use
|
|
30
|
+
# @return [void]
|
|
31
|
+
# @raise [Treaty::Exceptions::Validation] if entity_class is not a valid Treaty::Entity subclass
|
|
32
|
+
def use_entity(entity_class)
|
|
33
|
+
validate_entity_class!(entity_class)
|
|
34
|
+
@entity_class = entity_class
|
|
15
35
|
end
|
|
16
36
|
|
|
37
|
+
# Returns collection of attributes from the entity class
|
|
38
|
+
#
|
|
39
|
+
# @return [Collection] Collection of attributes
|
|
17
40
|
def collection_of_attributes
|
|
18
|
-
|
|
19
|
-
end
|
|
41
|
+
return Treaty::Attribute::Collection.new if @entity_class.nil?
|
|
20
42
|
|
|
21
|
-
|
|
43
|
+
@entity_class.collection_of_attributes
|
|
44
|
+
end
|
|
22
45
|
|
|
46
|
+
# Handles DSL methods for defining attributes
|
|
47
|
+
#
|
|
48
|
+
# This allows the factory to be used with method_missing
|
|
49
|
+
# for backwards compatibility with direct method calls.
|
|
50
|
+
# Creates an anonymous Request::Entity class on first use.
|
|
23
51
|
def method_missing(type, *helpers, **options, &block)
|
|
24
|
-
|
|
52
|
+
# If no entity class yet, create one
|
|
53
|
+
@entity_class ||= Class.new(Entity)
|
|
25
54
|
|
|
26
|
-
|
|
55
|
+
# Call the method on the entity class
|
|
56
|
+
@entity_class.public_send(type, *helpers, **options, &block)
|
|
27
57
|
end
|
|
28
58
|
|
|
29
59
|
def respond_to_missing?(name, *)
|
|
30
60
|
super
|
|
31
61
|
end
|
|
62
|
+
|
|
63
|
+
private
|
|
64
|
+
|
|
65
|
+
# Validates that the provided entity_class is a valid Treaty::Entity subclass
|
|
66
|
+
#
|
|
67
|
+
# @param entity_class [Class] Entity class to validate
|
|
68
|
+
# @raise [Treaty::Exceptions::Validation] if entity_class is not a valid Treaty::Entity subclass
|
|
69
|
+
def validate_entity_class!(entity_class)
|
|
70
|
+
return if entity_class.is_a?(Class) && entity_class < Treaty::Entity
|
|
71
|
+
|
|
72
|
+
raise Treaty::Exceptions::Validation,
|
|
73
|
+
I18n.t(
|
|
74
|
+
"treaty.request.factory.invalid_entity_class",
|
|
75
|
+
type: entity_class.class,
|
|
76
|
+
value: entity_class
|
|
77
|
+
)
|
|
78
|
+
end
|
|
32
79
|
end
|
|
33
80
|
end
|
|
34
81
|
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Treaty
|
|
4
|
+
module Request
|
|
5
|
+
# Validator for request data
|
|
6
|
+
class Validator
|
|
7
|
+
class << self
|
|
8
|
+
# Validates request parameters against the request definition
|
|
9
|
+
#
|
|
10
|
+
# @param params [Hash] Request parameters to validate
|
|
11
|
+
# @param version_factory [Versions::Factory] Version factory with request definition
|
|
12
|
+
# @return [Hash] Validated and transformed parameters
|
|
13
|
+
def validate!(params:, version_factory:)
|
|
14
|
+
new(params:, version_factory:).validate!
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def initialize(params:, version_factory:)
|
|
19
|
+
@params = params
|
|
20
|
+
@version_factory = version_factory
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def validate!
|
|
24
|
+
validate_request_attributes!
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def request_data
|
|
30
|
+
@request_data ||= begin
|
|
31
|
+
@params.to_unsafe_h
|
|
32
|
+
rescue NoMethodError
|
|
33
|
+
@params
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def validate_request_attributes! # rubocop:disable Metrics/MethodLength
|
|
38
|
+
return request_data unless adapter_strategy?
|
|
39
|
+
return request_data unless request_attributes_exist?
|
|
40
|
+
|
|
41
|
+
# For adapter strategy with attributes defined:
|
|
42
|
+
orchestrator_class = Class.new(Treaty::Attribute::Validation::Orchestrator::Base) do
|
|
43
|
+
define_method(:collection_of_attributes) do
|
|
44
|
+
@version_factory.request_factory.collection_of_attributes
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
orchestrator_class.validate!(
|
|
49
|
+
version_factory: @version_factory,
|
|
50
|
+
data: request_data
|
|
51
|
+
)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def adapter_strategy?
|
|
55
|
+
!@version_factory.strategy_instance.direct?
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def request_attributes_exist?
|
|
59
|
+
return false if @version_factory.request_factory&.collection_of_attributes&.empty?
|
|
60
|
+
|
|
61
|
+
@version_factory.request_factory.collection_of_attributes.exists?
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Treaty
|
|
4
|
+
module Response
|
|
5
|
+
# Entity class for response definitions.
|
|
6
|
+
# Attributes are optional by default.
|
|
7
|
+
#
|
|
8
|
+
# This class is used internally when defining response blocks.
|
|
9
|
+
# When you write a response block, Treaty creates an anonymous
|
|
10
|
+
# class based on Response::Entity.
|
|
11
|
+
class Entity
|
|
12
|
+
include Treaty::Attribute::DSL
|
|
13
|
+
|
|
14
|
+
class << self
|
|
15
|
+
private
|
|
16
|
+
|
|
17
|
+
# Creates a Response::Attribute::Attribute for this Response::Entity class
|
|
18
|
+
#
|
|
19
|
+
# @return [Response::Attribute::Attribute] Created attribute instance
|
|
20
|
+
def create_attribute(name, type, *helpers, nesting_level:, **options, &block)
|
|
21
|
+
Attribute::Attribute.new(
|
|
22
|
+
name,
|
|
23
|
+
type,
|
|
24
|
+
*helpers,
|
|
25
|
+
nesting_level:,
|
|
26
|
+
**options,
|
|
27
|
+
&block
|
|
28
|
+
)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|