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