lib/esquema/schema_enhancer.rb
# frozen_string_literal: true require "date" require "bigdecimal" require_relative "keyword_validator" module Esquema # The SchemaEnhancer class is responsible for enhancing the schema of a model. class SchemaEnhancer attr_reader :model def initialize(model, schema_enhancements) @schema_enhancements = schema_enhancements @model = model end # Sets the description for the model. # # @param description [String] The description of the model. def model_description(description) @schema_enhancements[:model_description] = description end # Sets the title for the model. # # @param title [String] The title of the model. def model_title(title) @schema_enhancements[:model_title] = title end # Adds a property to the schema. # # @param name [Symbol] The name of the property. # @param options [Hash] Additional options for the property. def property(name, options = {}) validate_property_as_attribute_for(name, options) type = resolve_type(name, options) KeywordValidator.validate!(name, type, options) @schema_enhancements[:properties] ||= {} @schema_enhancements[:properties][name] = options end # Adds a virtual property to the schema. # # @param name [Symbol] The name of the virtual property. # @param options [Hash] Additional options for the virtual property. def virtual_property(name, options = {}) options[:virtual] = true property(name, options) end private # Resolves the type of a property. # # @param name [Symbol] The name of the property. # @param options [Hash] Additional options for the property. # @return [Symbol] The resolved type of the property. def resolve_type(name, options = {}) if options[:virtual] == true options[:type] else model.type_for_attribute(name).type end end # Retrieves the valid properties for the model. # # @return [Array<Symbol>] The valid properties for the model. def valid_properties @valid_properties ||= begin properties = model.column_names + model.reflect_on_all_associations.map(&:name) properties.map(&:to_sym) end end # Validates that a property is a valid attribute for the model. # # @param prop_name [Symbol] The name of the property. # @param options [Hash] Additional options for the property. # @raise [ArgumentError] If the property is not a valid attribute for the model. def validate_property_as_attribute_for(prop_name, options = {}) return if options[:virtual] == true raise ArgumentError, "`#{prop_name}` is not a model attribute." unless valid_properties.include?(prop_name.to_sym) end end end