Class: Schemable::AttributeSchemaGenerator
- Inherits:
-
Object
- Object
- Schemable::AttributeSchemaGenerator
- Defined in:
- lib/schemable/attribute_schema_generator.rb
Overview
The AttributeSchemaGenerator class is responsible for generating JSON schemas for model attributes. It includes methods for generating the overall schema and individual attribute schemas.
Instance Attribute Summary collapse
-
#configuration ⇒ Object
readonly
Returns the value of attribute configuration.
-
#model ⇒ Object
readonly
Returns the value of attribute model.
-
#model_definition ⇒ Object
readonly
Returns the value of attribute model_definition.
-
#response ⇒ Object
readonly
Returns the value of attribute response.
-
#schema_modifier ⇒ Object
readonly
Returns the value of attribute schema_modifier.
Instance Method Summary collapse
-
#generate ⇒ Hash
Generates the JSON schema for the model attributes.
-
#generate_attribute_schema(attribute) ⇒ Hash
Generates the JSON schema for a specific attribute.
-
#initialize(model_definition) ⇒ AttributeSchemaGenerator
constructor
Initializes a new AttributeSchemaGenerator instance.
Constructor Details
#initialize(model_definition) ⇒ AttributeSchemaGenerator
Initializes a new AttributeSchemaGenerator instance.
14 15 16 17 18 19 20 |
# File 'lib/schemable/attribute_schema_generator.rb', line 14 def initialize(model_definition) @model_definition = model_definition @model = model_definition.model @configuration = Schemable.configuration @schema_modifier = SchemaModifier.new @response = nil end |
Instance Attribute Details
#configuration ⇒ Object (readonly)
Returns the value of attribute configuration.
7 8 9 |
# File 'lib/schemable/attribute_schema_generator.rb', line 7 def configuration @configuration end |
#model ⇒ Object (readonly)
Returns the value of attribute model.
7 8 9 |
# File 'lib/schemable/attribute_schema_generator.rb', line 7 def model @model end |
#model_definition ⇒ Object (readonly)
Returns the value of attribute model_definition.
7 8 9 |
# File 'lib/schemable/attribute_schema_generator.rb', line 7 def model_definition @model_definition end |
#response ⇒ Object (readonly)
Returns the value of attribute response.
7 8 9 |
# File 'lib/schemable/attribute_schema_generator.rb', line 7 def response @response end |
#schema_modifier ⇒ Object (readonly)
Returns the value of attribute schema_modifier.
7 8 9 |
# File 'lib/schemable/attribute_schema_generator.rb', line 7 def schema_modifier @schema_modifier end |
Instance Method Details
#generate ⇒ Hash
Generates the JSON schema for the model attributes.
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/schemable/attribute_schema_generator.rb', line 27 def generate schema = { type: :object, properties: @model_definition.attributes.index_with do |attr| generate_attribute_schema(attr) end } # Rename enum attributes to remove the suffix or prefix if mongoid is used if @configuration.orm == :mongoid schema[:properties].transform_keys! do |key| key.to_s.gsub(@configuration.enum_prefix_for_simple_enum || @configuration.enum_suffix_for_simple_enum, '') end end # modify the schema to include additional response relations schema = @schema_modifier.add_properties(schema, @model_definition.additional_response_attributes, 'properties') # modify the schema to exclude response relations @model_definition.excluded_response_attributes.each do |key| schema = @schema_modifier.delete_properties(schema, "properties.#{key}") end schema end |
#generate_attribute_schema(attribute) ⇒ Hash
Generates the JSON schema for a specific attribute.
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/schemable/attribute_schema_generator.rb', line 59 def generate_attribute_schema(attribute) if @configuration.orm == :mongoid # Get the column hash for the attribute attribute_hash = @model.fields[attribute.to_s] # Check if this attribute has a custom JSON Schema definition return @model_definition.array_types[attribute] if @model_definition.array_types.keys.include?(attribute.to_sym) return @model_definition.additional_response_attributes[attribute] if @model_definition.additional_response_attributes.keys.include?(attribute) # Check if this is an array attribute return @configuration.type_mapper(:array) if attribute_hash.try(:[], 'options').try(:[], 'type') == 'Array' # Check if this is an enum attribute @response = if attribute_hash.name.end_with?('_cd') @configuration.type_mapper(:string) else # Map the column type to a JSON Schema type if none of the above conditions are met @configuration.type_mapper(attribute_hash.try(:type).to_s.downcase.to_sym) end elsif @configuration.orm == :active_record # Get the column hash for the attribute attribute_hash = @model.columns_hash[attribute.to_s] # Check if this attribute has a custom JSON Schema definition return @model_definition.array_types[attribute] if @model_definition.array_types.keys.include?(attribute.to_sym) return @model_definition.additional_response_attributes[attribute] if @model_definition.additional_response_attributes.keys.include?(attribute) # Check if this is an array attribute return @configuration.type_mapper(:array) if attribute_hash.as_json.try(:[], 'sql_type_metadata').try(:[], 'sql_type').include?('[]') # Map the column type to a JSON Schema type if none of the above conditions are met @response = @configuration.type_mapper(attribute_hash.try(:type)) else raise 'ORM not supported' end # If the attribute is nullable, modify the schema accordingly return @schema_modifier.add_properties(@response, { nullable: true }, '.') if @response && @model_definition.nullable_attributes.include?(attribute) # If attribute is an enum, modify the schema accordingly if @configuration.custom_defined_enum_method && @model.respond_to?(@configuration.custom_defined_enum_method) defined_enums = @model.send(@configuration.custom_defined_enum_method) enum_attribute = attribute.to_s.gsub(@configuration.enum_prefix_for_simple_enum || @configuration.enum_suffix_for_simple_enum, '').to_s if @response && defined_enums[enum_attribute].present? return @schema_modifier.add_properties( @response, { enum: defined_enums[enum_attribute].keys, default: @model_definition.default_value_for_enum_attributes[attribute.to_sym] || defined_enums[enum_attribute].keys.first }, '.' ) end elsif @model.respond_to?(:defined_enums) && @response && @model.defined_enums.key?(attribute.to_s) return @schema_modifier.add_properties( @response, { enum: @model.defined_enums[attribute.to_s].keys, default: @model_definition.default_value_for_enum_attributes[attribute.to_sym] || @model.defined_enums[attribute.to_s].keys.first }, '.' ) end return @response unless @response.nil? # 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 if @configuration.use_serialized_instance serialized_instance = @model_definition.serialized_instance type_from_instance = serialized_instance.as_json['data']['attributes'][attribute.to_s.camelize(:lower)]&.class&.name&.downcase @response = @configuration.type_mapper(type_from_instance) if type_from_instance.present? return @response unless @response.nil? end # If we still haven't found a schema type, default to object @configuration.type_mapper(:object) rescue NoMethodError # Log a warning if the attribute does not exist on the @model Rails.logger.warn("\e[33mWARNING: #{@model} does not have an attribute named \e[31m#{attribute}\e[0m") {} end |