schemable 0.1.4 → 1.0.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +5 -1
- data/CHANGELOG.md +8 -3
- data/Gemfile +5 -5
- data/Gemfile.lock +0 -136
- data/README.md +327 -101
- data/lib/generators/schemable/install_generator.rb +3 -13
- data/lib/generators/schemable/model_generator.rb +1 -16
- data/lib/schemable/attribute_schema_generator.rb +146 -0
- data/lib/schemable/configuration.rb +114 -0
- data/lib/schemable/definition.rb +335 -0
- data/lib/schemable/included_schema_generator.rb +107 -0
- data/lib/schemable/relationship_schema_generator.rb +119 -0
- data/lib/schemable/request_schema_generator.rb +88 -0
- data/lib/schemable/response_schema_generator.rb +124 -0
- data/lib/schemable/schema_modifier.rb +248 -0
- data/lib/schemable/version.rb +1 -1
- data/lib/schemable.rb +60 -937
- data/lib/templates/schemable.rb +76 -0
- data/schemable.gemspec +2 -5
- data/sig/schemable/attribute_schema_generator.rbs +13 -0
- data/sig/schemable/configuration.rbs +21 -0
- data/sig/schemable/definition.rbs +33 -0
- data/sig/schemable/included_schema_generator.rbs +11 -0
- data/sig/schemable/relationship_schema_generator.rbs +11 -0
- data/sig/schemable/request_schema_generator.rbs +10 -0
- data/sig/schemable/response_schema_generator.rbs +13 -0
- data/sig/schemable/schema_modifier.rbs +9 -0
- data/sig/schemable.rbs +4 -1
- metadata +23 -36
- data/lib/templates/common_definitions.rb +0 -13
- data/lib/templates/serializers_helper.rb +0 -7
@@ -0,0 +1,146 @@
|
|
1
|
+
module Schemable
|
2
|
+
# The AttributeSchemaGenerator class is responsible for generating JSON schemas for model attributes.
|
3
|
+
# It includes methods for generating the overall schema and individual attribute schemas.
|
4
|
+
#
|
5
|
+
# @see Schemable
|
6
|
+
class AttributeSchemaGenerator
|
7
|
+
attr_reader :model_definition, :configuration, :model, :schema_modifier, :response
|
8
|
+
|
9
|
+
# Initializes a new AttributeSchemaGenerator instance.
|
10
|
+
#
|
11
|
+
# @param model_definition [ModelDefinition] The model definition to generate the schema for.
|
12
|
+
# @example
|
13
|
+
# generator = AttributeSchemaGenerator.new(model_definition)
|
14
|
+
def initialize(model_definition)
|
15
|
+
@model_definition = model_definition
|
16
|
+
@model = model_definition.model
|
17
|
+
@configuration = Schemable.configuration
|
18
|
+
@schema_modifier = SchemaModifier.new
|
19
|
+
@response = nil
|
20
|
+
end
|
21
|
+
|
22
|
+
# Generates the JSON schema for the model attributes.
|
23
|
+
#
|
24
|
+
# @return [Hash] The generated schema.
|
25
|
+
# @example
|
26
|
+
# schema = generator.generate
|
27
|
+
def generate
|
28
|
+
schema = {
|
29
|
+
type: :object,
|
30
|
+
properties: @model_definition.attributes.index_with do |attr|
|
31
|
+
generate_attribute_schema(attr)
|
32
|
+
end
|
33
|
+
}
|
34
|
+
|
35
|
+
# Rename enum attributes to remove the suffix or prefix if mongoid is used
|
36
|
+
if @configuration.orm == :mongoid
|
37
|
+
schema[:properties].transform_keys! do |key|
|
38
|
+
key.to_s.gsub(@configuration.enum_prefix_for_simple_enum || @configuration.enum_suffix_for_simple_enum, '')
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# modify the schema to include additional response relations
|
43
|
+
schema = @schema_modifier.add_properties(schema, @model_definition.additional_response_attributes, 'properties')
|
44
|
+
|
45
|
+
# modify the schema to exclude response relations
|
46
|
+
@model_definition.excluded_response_attributes.each do |key|
|
47
|
+
schema = @schema_modifier.delete_properties(schema, "properties.#{key}")
|
48
|
+
end
|
49
|
+
|
50
|
+
schema
|
51
|
+
end
|
52
|
+
|
53
|
+
# Generates the JSON schema for a specific attribute.
|
54
|
+
#
|
55
|
+
# @param attribute [Symbol, String] The attribute to generate the schema for.
|
56
|
+
# @return [Hash] The generated schema for the attribute.
|
57
|
+
# @example
|
58
|
+
# attribute_schema = generator.generate_attribute_schema(:attribute_name)
|
59
|
+
def generate_attribute_schema(attribute)
|
60
|
+
if @configuration.orm == :mongoid
|
61
|
+
# Get the column hash for the attribute
|
62
|
+
attribute_hash = @model.fields[attribute.to_s]
|
63
|
+
|
64
|
+
# Check if this attribute has a custom JSON Schema definition
|
65
|
+
return @model_definition.array_types[attribute] if @model_definition.array_types.keys.include?(attribute.to_sym)
|
66
|
+
return @model_definition.additional_response_attributes[attribute] if @model_definition.additional_response_attributes.keys.include?(attribute)
|
67
|
+
|
68
|
+
# Check if this is an array attribute
|
69
|
+
return @configuration.type_mapper(:array) if attribute_hash.try(:[], 'options').try(:[], 'type') == 'Array'
|
70
|
+
|
71
|
+
# Check if this is an enum attribute
|
72
|
+
@response = if attribute_hash.name.end_with?('_cd')
|
73
|
+
@configuration.type_mapper(:string)
|
74
|
+
else
|
75
|
+
# Map the column type to a JSON Schema type if none of the above conditions are met
|
76
|
+
@configuration.type_mapper(attribute_hash.try(:type).to_s.downcase.to_sym)
|
77
|
+
end
|
78
|
+
|
79
|
+
elsif @configuration.orm == :active_record
|
80
|
+
# Get the column hash for the attribute
|
81
|
+
attribute_hash = @model.columns_hash[attribute.to_s]
|
82
|
+
|
83
|
+
# Check if this attribute has a custom JSON Schema definition
|
84
|
+
return @model_definition.array_types[attribute] if @model_definition.array_types.keys.include?(attribute.to_sym)
|
85
|
+
return @model_definition.additional_response_attributes[attribute] if @model_definition.additional_response_attributes.keys.include?(attribute)
|
86
|
+
|
87
|
+
# Check if this is an array attribute
|
88
|
+
return @configuration.type_mapper(:array) if attribute_hash.as_json.try(:[], 'sql_type_metadata').try(:[], 'sql_type').include?('[]')
|
89
|
+
|
90
|
+
# Map the column type to a JSON Schema type if none of the above conditions are met
|
91
|
+
@response = @configuration.type_mapper(attribute_hash.try(:type))
|
92
|
+
|
93
|
+
else
|
94
|
+
raise 'ORM not supported'
|
95
|
+
end
|
96
|
+
|
97
|
+
# If the attribute is nullable, modify the schema accordingly
|
98
|
+
return @schema_modifier.add_properties(@response, { nullable: true }, '.') if @response && @model_definition.nullable_attributes.include?(attribute)
|
99
|
+
|
100
|
+
# If attribute is an enum, modify the schema accordingly
|
101
|
+
if @configuration.custom_defined_enum_method && @model.respond_to?(@configuration.custom_defined_enum_method)
|
102
|
+
defined_enums = @model.send(@configuration.custom_defined_enum_method)
|
103
|
+
enum_attribute = attribute.to_s.gsub(@configuration.enum_prefix_for_simple_enum || @configuration.enum_suffix_for_simple_enum, '').to_s
|
104
|
+
if @response && defined_enums[enum_attribute].present?
|
105
|
+
return @schema_modifier.add_properties(
|
106
|
+
@response,
|
107
|
+
{
|
108
|
+
enum: defined_enums[enum_attribute].keys,
|
109
|
+
default: @model_definition.default_value_for_enum_attributes[attribute.to_sym] || defined_enums[enum_attribute].keys.first
|
110
|
+
},
|
111
|
+
'.'
|
112
|
+
)
|
113
|
+
end
|
114
|
+
elsif @model.respond_to?(:defined_enums) && @response && @model.defined_enums.key?(attribute.to_s)
|
115
|
+
return @schema_modifier.add_properties(
|
116
|
+
@response,
|
117
|
+
{
|
118
|
+
enum: @model.defined_enums[attribute.to_s].keys,
|
119
|
+
default: @model_definition.default_value_for_enum_attributes[attribute.to_sym] || @model.defined_enums[attribute.to_s].keys.first
|
120
|
+
},
|
121
|
+
'.'
|
122
|
+
)
|
123
|
+
end
|
124
|
+
|
125
|
+
return @response unless @response.nil?
|
126
|
+
|
127
|
+
# If we haven't found a schema type yet, try to infer it from the type of the attribute's value in the instance data
|
128
|
+
if @configuration.use_serialized_instance
|
129
|
+
serialized_instance = @model_definition.serialized_instance
|
130
|
+
|
131
|
+
type_from_instance = serialized_instance.as_json['data']['attributes'][attribute.to_s.camelize(:lower)]&.class&.name&.downcase
|
132
|
+
|
133
|
+
@response = @configuration.type_mapper(type_from_instance) if type_from_instance.present?
|
134
|
+
|
135
|
+
return @response unless @response.nil?
|
136
|
+
end
|
137
|
+
|
138
|
+
# If we still haven't found a schema type, default to object
|
139
|
+
@configuration.type_mapper(:object)
|
140
|
+
rescue NoMethodError
|
141
|
+
# Log a warning if the attribute does not exist on the @model
|
142
|
+
Rails.logger.warn("\e[33mWARNING: #{@model} does not have an attribute named \e[31m#{attribute}\e[0m")
|
143
|
+
{}
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
module Schemable
|
2
|
+
# The Configuration class provides a set of configuration options for the Schemable module.
|
3
|
+
# It includes options for setting the ORM, handling enums, custom type mappers, and more.
|
4
|
+
# It is worth noting that the configuration options are global, and will affect all Definitions.
|
5
|
+
#
|
6
|
+
# @see Schemable
|
7
|
+
class Configuration
|
8
|
+
attr_accessor(
|
9
|
+
:orm,
|
10
|
+
:float_as_string,
|
11
|
+
:decimal_as_string,
|
12
|
+
:pagination_enabled,
|
13
|
+
:custom_type_mappers,
|
14
|
+
:use_serialized_instance,
|
15
|
+
:custom_defined_enum_method,
|
16
|
+
:enum_prefix_for_simple_enum,
|
17
|
+
:enum_suffix_for_simple_enum,
|
18
|
+
:custom_meta_response_schema,
|
19
|
+
:infer_attributes_from_custom_method,
|
20
|
+
:infer_attributes_from_jsonapi_serializable
|
21
|
+
)
|
22
|
+
|
23
|
+
# Initializes a new Configuration instance with default values.
|
24
|
+
def initialize
|
25
|
+
@orm = :active_record # orm options are :active_record, :mongoid
|
26
|
+
@float_as_string = false
|
27
|
+
@custom_type_mappers = {}
|
28
|
+
@pagination_enabled = true
|
29
|
+
@decimal_as_string = false
|
30
|
+
@use_serialized_instance = false
|
31
|
+
@custom_defined_enum_method = nil
|
32
|
+
@custom_meta_response_schema = nil
|
33
|
+
@enum_prefix_for_simple_enum = nil
|
34
|
+
@enum_suffix_for_simple_enum = nil
|
35
|
+
@infer_attributes_from_custom_method = nil
|
36
|
+
@infer_attributes_from_jsonapi_serializable = false
|
37
|
+
end
|
38
|
+
|
39
|
+
# Returns a type mapper for a given type name.
|
40
|
+
#
|
41
|
+
# @note If a custom type mapper is defined for the given type name, it will be returned.
|
42
|
+
#
|
43
|
+
# @example
|
44
|
+
# type_mapper(:string) #=> { type: :string }
|
45
|
+
#
|
46
|
+
# @param type_name [Symbol, String] The name of the type.
|
47
|
+
# @return [Hash] The type mapper for the given type name.
|
48
|
+
def type_mapper(type_name)
|
49
|
+
return @custom_type_mappers[type_name] if @custom_type_mappers.key?(type_name.to_sym)
|
50
|
+
|
51
|
+
{
|
52
|
+
text: { type: :string },
|
53
|
+
string: { type: :string },
|
54
|
+
symbol: { type: :string },
|
55
|
+
integer: { type: :integer },
|
56
|
+
boolean: { type: :boolean },
|
57
|
+
date: { type: :string, format: :date },
|
58
|
+
time: { type: :string, format: :time },
|
59
|
+
json: { type: :object, properties: {} },
|
60
|
+
hash: { type: :object, properties: {} },
|
61
|
+
jsonb: { type: :object, properties: {} },
|
62
|
+
object: { type: :object, properties: {} },
|
63
|
+
binary: { type: :string, format: :binary },
|
64
|
+
trueclass: { type: :boolean, default: true },
|
65
|
+
falseclass: { type: :boolean, default: false },
|
66
|
+
datetime: { type: :string, format: :'date-time' },
|
67
|
+
big_decimal: { type: (@decimal_as_string ? :string : :number).to_s.to_sym, format: :double },
|
68
|
+
'bson/objectid': { type: :string, format: :object_id },
|
69
|
+
'mongoid/boolean': { type: :boolean },
|
70
|
+
'mongoid/stringified_symbol': { type: :string },
|
71
|
+
'active_support/time_with_zone': { type: :string, format: :date_time },
|
72
|
+
float: {
|
73
|
+
type: (@float_as_string ? :string : :number).to_s.to_sym,
|
74
|
+
format: :float
|
75
|
+
},
|
76
|
+
decimal: {
|
77
|
+
type: (@decimal_as_string ? :string : :number).to_s.to_sym,
|
78
|
+
format: :double
|
79
|
+
},
|
80
|
+
array: {
|
81
|
+
type: :array,
|
82
|
+
items: {
|
83
|
+
anyOf: [
|
84
|
+
{ type: :string },
|
85
|
+
{ type: :integer },
|
86
|
+
{ type: :boolean },
|
87
|
+
{ type: :number, format: :float },
|
88
|
+
{ type: :object, properties: {} },
|
89
|
+
{ type: :number, format: :double }
|
90
|
+
]
|
91
|
+
}
|
92
|
+
}
|
93
|
+
}[type_name.to_s.underscore.try(:to_sym)]
|
94
|
+
end
|
95
|
+
|
96
|
+
# Adds a custom type mapper for a given type name.
|
97
|
+
#
|
98
|
+
# @example
|
99
|
+
# add_custom_type_mapper(:custom_type, { type: :custom })
|
100
|
+
# type_mapper(:custom_type) #=> { type: :custom }
|
101
|
+
#
|
102
|
+
# # It preferable to invoke this method in the config/initializers/schemable.rb file.
|
103
|
+
# # This way, the custom type mapper will be available for all Definitions.
|
104
|
+
# Schemable.configure do |config|
|
105
|
+
# config.add_custom_type_mapper(:custom_type, { type: :custom })
|
106
|
+
# end
|
107
|
+
#
|
108
|
+
# @param type_name [Symbol, String] The name of the type.
|
109
|
+
# @param mapping [Hash] The mapping to add.
|
110
|
+
def add_custom_type_mapper(type_name, mapping)
|
111
|
+
custom_type_mappers[type_name.to_sym] = mapping
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,335 @@
|
|
1
|
+
module Schemable
|
2
|
+
# The Definition class provides a blueprint for generating and modifying schemas.
|
3
|
+
# It includes methods for handling attributes, relationships, and various request and response attributes.
|
4
|
+
# The definition class is meant to be inherited by a class that represents a model.
|
5
|
+
# This class should be configured to match the model's attributes and relationships.
|
6
|
+
# The default configuration is set in this class, but can be overridden in the model's definition class.
|
7
|
+
#
|
8
|
+
# @see Schemable
|
9
|
+
class Definition
|
10
|
+
attr_reader :configuration
|
11
|
+
attr_writer :relationships, :additional_create_request_attributes, :additional_update_request_attributes
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@configuration = Schemable.configuration
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns the serializer of the model for the definition.
|
18
|
+
# @example
|
19
|
+
# UsersSerializer
|
20
|
+
# @return [JSONAPI::Serializable::Resource, nil] The model's serializer.
|
21
|
+
def serializer
|
22
|
+
raise NotImplementedError, 'You must implement the serializer method in the definition class in order to use the infer_serializer_from_jsonapi_serializable configuration option.' if configuration.infer_attributes_from_jsonapi_serializable
|
23
|
+
|
24
|
+
nil
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns the attributes for the definition based on the configuration.
|
28
|
+
# The attributes are inferred from the model's attribute names by default.
|
29
|
+
# If the infer_attributes_from_custom_method configuration option is set, the attributes are inferred from the method specified.
|
30
|
+
# If the infer_attributes_from_jsonapi_serializable configuration option is set, the attributes are inferred from the serializer's attribute blocks.
|
31
|
+
#
|
32
|
+
# @example
|
33
|
+
# attributes = definition.attributes # => [:id, :name, :email]
|
34
|
+
#
|
35
|
+
# @return [Array<Symbol>] The attributes used for generating the schemas.
|
36
|
+
def attributes
|
37
|
+
return (serializer&.attribute_blocks&.transform_keys { |key| key.to_s.underscore.to_sym }&.keys || nil) if configuration.infer_attributes_from_jsonapi_serializable
|
38
|
+
|
39
|
+
return model.send(configuration.infer_attributes_from_custom_method).map(&:to_sym) if configuration.infer_attributes_from_custom_method
|
40
|
+
|
41
|
+
model.attribute_names.map(&:to_sym)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Returns the relationships defined in the serializer.
|
45
|
+
#
|
46
|
+
# @note Note that the format of the relationships is as follows:
|
47
|
+
# {
|
48
|
+
# belongs_to: { relationship_name: relationship_definition },
|
49
|
+
# has_many: { relationship_name: relationship_definition },
|
50
|
+
# addition_to_included: { relationship_name: relationship_definition }
|
51
|
+
# }
|
52
|
+
#
|
53
|
+
# @note The addition_to_included is used to define the extra nested relationships that are not defined in the belongs_to or has_many for included.
|
54
|
+
#
|
55
|
+
# @example
|
56
|
+
# {
|
57
|
+
# belongs_to: {
|
58
|
+
# district: Swagger::Definitions::District,
|
59
|
+
# user: Swagger::Definitions::User
|
60
|
+
# },
|
61
|
+
# has_many: {
|
62
|
+
# applicants: Swagger::Definitions::Applicant,
|
63
|
+
# },
|
64
|
+
# addition_to_included: {
|
65
|
+
# applicants: Swagger::Definitions::Applicant
|
66
|
+
# }
|
67
|
+
# }
|
68
|
+
#
|
69
|
+
# @return [Hash] The relationships defined in the serializer.
|
70
|
+
def relationships
|
71
|
+
{ belongs_to: {}, has_many: {} }
|
72
|
+
end
|
73
|
+
|
74
|
+
# Returns a hash of all the arrays defined for the model.
|
75
|
+
# The schema for each array is defined in the definition class manually.
|
76
|
+
# This method must be implemented in the definition class if there are any arrays.
|
77
|
+
#
|
78
|
+
# @return [Hash] The arrays of the model and their schemas.
|
79
|
+
#
|
80
|
+
# @example
|
81
|
+
# {
|
82
|
+
# metadata: {
|
83
|
+
# type: :array,
|
84
|
+
# items: {
|
85
|
+
# type: :object, nullable: true,
|
86
|
+
# properties: { name: { type: :string, nullable: true } }
|
87
|
+
# }
|
88
|
+
# }
|
89
|
+
# }
|
90
|
+
def array_types
|
91
|
+
{}
|
92
|
+
end
|
93
|
+
|
94
|
+
# Attributes that are not required in the create request.
|
95
|
+
#
|
96
|
+
# @example
|
97
|
+
# optional_create_request_attributes = definition.optional_create_request_attributes
|
98
|
+
# # => [:email]
|
99
|
+
#
|
100
|
+
# @return [Array<Symbol>] The attributes that are not required in the create request.
|
101
|
+
def optional_create_request_attributes
|
102
|
+
%i[]
|
103
|
+
end
|
104
|
+
|
105
|
+
# Attributes that are not required in the update request.
|
106
|
+
#
|
107
|
+
# @example
|
108
|
+
# optional_update_request_attributes = definition.optional_update_request_attributes
|
109
|
+
# # => [:email]
|
110
|
+
#
|
111
|
+
# @return [Array<Symbol>] The attributes that are not required in the update request.
|
112
|
+
def optional_update_request_attributes
|
113
|
+
%i[]
|
114
|
+
end
|
115
|
+
|
116
|
+
# Returns the attributes that are nullable in the request/response body.
|
117
|
+
# This means that they can be present in the request/response body but they can be null.
|
118
|
+
# They are not required to be present in the request body.
|
119
|
+
#
|
120
|
+
# @example
|
121
|
+
# [:name, :email]
|
122
|
+
#
|
123
|
+
# @return [Array<Symbol>] The attributes that are nullable in the request/response body.
|
124
|
+
def nullable_attributes
|
125
|
+
%i[]
|
126
|
+
end
|
127
|
+
|
128
|
+
# Returns the additional create request attributes that are not automatically generated.
|
129
|
+
# These attributes are appended to the create request schema.
|
130
|
+
#
|
131
|
+
# @example
|
132
|
+
# { name: { type: :string } }
|
133
|
+
#
|
134
|
+
# @return [Hash] The additional create request attributes that are not automatically generated (if any).
|
135
|
+
def additional_create_request_attributes
|
136
|
+
{}
|
137
|
+
end
|
138
|
+
|
139
|
+
# Returns the additional update request attributes that are not automatically generated.
|
140
|
+
# These attributes are appended to the update request schema.
|
141
|
+
#
|
142
|
+
# @example
|
143
|
+
# { name: { type: :string } }
|
144
|
+
#
|
145
|
+
# @return [Hash] The additional update request attributes that are not automatically generated (if any).
|
146
|
+
def additional_update_request_attributes
|
147
|
+
{}
|
148
|
+
end
|
149
|
+
|
150
|
+
# Returns the additional response attributes that are not automatically generated. These attributes are appended to the response schema.
|
151
|
+
#
|
152
|
+
# @example
|
153
|
+
# { name: { type: :string } }
|
154
|
+
#
|
155
|
+
# @return [Hash] The additional response attributes that are not automatically generated (if any).
|
156
|
+
def additional_response_attributes
|
157
|
+
{}
|
158
|
+
end
|
159
|
+
|
160
|
+
# Returns the additional response relations that are not automatically generated.
|
161
|
+
# These relations are appended to the response schema's relationships.
|
162
|
+
#
|
163
|
+
# @example
|
164
|
+
# {
|
165
|
+
# users: {
|
166
|
+
# type: :object,
|
167
|
+
# properties: {
|
168
|
+
# data: {
|
169
|
+
# type: :array,
|
170
|
+
# items: {
|
171
|
+
# type: :object,
|
172
|
+
# properties: {
|
173
|
+
# id: { type: :string },
|
174
|
+
# type: { type: :string }
|
175
|
+
# }
|
176
|
+
# }
|
177
|
+
# }
|
178
|
+
# }
|
179
|
+
# }
|
180
|
+
# }
|
181
|
+
#
|
182
|
+
# @return [Hash] The additional response relations that are not automatically generated (if any).
|
183
|
+
def additional_response_relations
|
184
|
+
{}
|
185
|
+
end
|
186
|
+
|
187
|
+
# Returns the additional response included that are not automatically generated.
|
188
|
+
# These included additions are appended to the response schema's included.
|
189
|
+
#
|
190
|
+
# @example
|
191
|
+
# {
|
192
|
+
# type: :object,
|
193
|
+
# properties: {
|
194
|
+
# id: { type: :string },
|
195
|
+
# type: { type: :string },
|
196
|
+
# attributes: {
|
197
|
+
# type: :object,
|
198
|
+
# properties: {
|
199
|
+
# name: { type: :string }
|
200
|
+
# }
|
201
|
+
# }
|
202
|
+
# }
|
203
|
+
# }
|
204
|
+
#
|
205
|
+
# @return [Hash] The additional response included that are not automatically generated (if any).
|
206
|
+
def additional_response_included
|
207
|
+
{}
|
208
|
+
end
|
209
|
+
|
210
|
+
# Returns the attributes that are excluded from the create request schema.
|
211
|
+
# These attributes are not required or not needed to be present in the create request body.
|
212
|
+
#
|
213
|
+
# @example
|
214
|
+
# [:id, :updated_at, :created_at]
|
215
|
+
#
|
216
|
+
# @return [Array<Symbol>] The attributes that are excluded from the create request schema.
|
217
|
+
def excluded_create_request_attributes
|
218
|
+
%i[]
|
219
|
+
end
|
220
|
+
|
221
|
+
# Returns the attributes that are excluded from the response schema.
|
222
|
+
# These attributes are not needed to be present in the response body.
|
223
|
+
#
|
224
|
+
# @example
|
225
|
+
# [:id, :updated_at, :created_at]
|
226
|
+
#
|
227
|
+
# @return [Array<Symbol>] The attributes that are excluded from the response schema.
|
228
|
+
def excluded_update_request_attributes
|
229
|
+
%i[]
|
230
|
+
end
|
231
|
+
|
232
|
+
# Returns the attributes that are excluded from the update request schema.
|
233
|
+
# These attributes are not required or not needed to be present in the update request body.
|
234
|
+
#
|
235
|
+
# @example
|
236
|
+
# [:id, :updated_at, :created_at]
|
237
|
+
#
|
238
|
+
# @return [Array<Symbol>] The attributes that are excluded from the update request schema.
|
239
|
+
def excluded_response_attributes
|
240
|
+
%i[]
|
241
|
+
end
|
242
|
+
|
243
|
+
# Returns the relationships that are excluded from the response schema.
|
244
|
+
# These relationships are not needed to be present in the response body.
|
245
|
+
#
|
246
|
+
# @example
|
247
|
+
# [:users, :applicants]
|
248
|
+
#
|
249
|
+
# @return [Array<Symbol>] The relationships that are excluded from the response schema.
|
250
|
+
def excluded_response_relations
|
251
|
+
%i[]
|
252
|
+
end
|
253
|
+
|
254
|
+
# Returns the included that are excluded from the response schema.
|
255
|
+
# These included are not needed to be present in the response body.
|
256
|
+
#
|
257
|
+
# @example
|
258
|
+
# [:users, :applicants]
|
259
|
+
#
|
260
|
+
# @todo
|
261
|
+
# This method is not used anywhere yet.
|
262
|
+
#
|
263
|
+
# @return [Array<Symbol>] The included that are excluded from the response schema.
|
264
|
+
def excluded_response_included
|
265
|
+
%i[]
|
266
|
+
end
|
267
|
+
|
268
|
+
# Returns the default value for the enum attributes.
|
269
|
+
#
|
270
|
+
# @example
|
271
|
+
# {
|
272
|
+
# status: 'pending',
|
273
|
+
# flag: 0
|
274
|
+
# }
|
275
|
+
#
|
276
|
+
# @return [Hash] The custom default values for the enum attributes.
|
277
|
+
def default_value_for_enum_attributes
|
278
|
+
{}
|
279
|
+
end
|
280
|
+
|
281
|
+
# Returns an instance of the model class that is already serialized into jsonapi format.
|
282
|
+
#
|
283
|
+
# @return [Hash] The serialized instance of the model class.
|
284
|
+
def serialized_instance
|
285
|
+
{}
|
286
|
+
end
|
287
|
+
|
288
|
+
# Returns the model class (Constantized from the definition class name)
|
289
|
+
#
|
290
|
+
# @example
|
291
|
+
# User
|
292
|
+
#
|
293
|
+
# @return [Class] The model class (Constantized from the definition class name)
|
294
|
+
def model
|
295
|
+
self.class.name.gsub('Swagger::Definitions::', '').constantize
|
296
|
+
end
|
297
|
+
|
298
|
+
# Returns the model name. Used for schema type naming.
|
299
|
+
#
|
300
|
+
# @return [String] The model name.
|
301
|
+
#
|
302
|
+
# @example
|
303
|
+
# 'users' for the User model
|
304
|
+
# 'citizen_applications' for the CitizenApplication model
|
305
|
+
def model_name
|
306
|
+
self.class.name.gsub('Swagger::Definitions::', '').pluralize.underscore.downcase
|
307
|
+
end
|
308
|
+
|
309
|
+
# Given a hash, it returns a new hash with all the keys camelized.
|
310
|
+
#
|
311
|
+
# @param hash [Hash] The hash with all the keys camelized.
|
312
|
+
#
|
313
|
+
# @return [Hash, Array] The hash with all the keys camelized.
|
314
|
+
#
|
315
|
+
# @example
|
316
|
+
# { first_name: 'John', last_name: 'Doe' } => { firstName: 'John', lastName: 'Doe' }
|
317
|
+
def camelize_keys(hash)
|
318
|
+
hash.deep_transform_keys { |key| key.to_s.camelize(:lower).to_sym }
|
319
|
+
end
|
320
|
+
|
321
|
+
# Returns the schema for the create request body, update request body, and response body.
|
322
|
+
#
|
323
|
+
# @return [Array<Hash>] The schema for the create request body, update request body, and response body.
|
324
|
+
def self.generate
|
325
|
+
instance = new
|
326
|
+
|
327
|
+
[
|
328
|
+
"#{instance.model}CreateRequest": instance.camelize_keys(RequestSchemaGenerator.new(instance).generate_for_create),
|
329
|
+
"#{instance.model}UpdateRequest": instance.camelize_keys(RequestSchemaGenerator.new(instance).generate_for_update),
|
330
|
+
"#{instance.model}Response": instance.camelize_keys(ResponseSchemaGenerator.new(instance).generate(collection: true)),
|
331
|
+
"#{instance.model}ResponseExpanded": instance.camelize_keys(ResponseSchemaGenerator.new(instance).generate(expand: true))
|
332
|
+
]
|
333
|
+
end
|
334
|
+
end
|
335
|
+
end
|