module Restspec module Schema # The Schema DSL is what should be used inside the `schemas.rb` file. # This class is related to the top-level namespace of the DSL. class DSL def initialize self.mixins = {} end # Generates a schema and sends the schema to an {SingleSchemaDSL} # instance for further definitions. # # @example # schema :book, root: true do # puts self.class # SingleSchemaDSL # puts self.schema.class # Schema # end # # @param name {Symbol} the schema's name # @param options {Hash} a set of options for {Schema#initialize} # @param definition A block that will be executed inside the context # of a {SingleSchemaDSL} object. def schema(name, options = {}, &definition) dsl = SingleSchemaDSL.new(name, options, mixins) dsl.instance_eval(&definition) Restspec::SchemaStore.store(dsl.schema) end # Generates a set of calls that can be executed in # many schemas with {SingleSchemaDSL#include_attributes}. # # They are useful to share attributes. # # @example # # mixin :timestamps do # attribute :created_at, date # attribute :updated_at, date # end # # schema :book do # include_attributes :timestamps # end # # schema :celphones do # include_attributes :timestamps # end # # @param name {Symbol} the mixin's name # @param definition A block that will be executed on demand # in an {SingleSchemaDSL} object's context. def mixin(name, &definition) mixins[name] = definition end private attr_accessor :mixins end # The DSL to use inside `schema` and `mixin` blocks of # a {DSL} instance block. It defines specific things of a # schema or a group of them. class SingleSchemaDSL include Types::TypeMethods # @return {Schema} the current schema attr_reader :schema def initialize(name, options = {}, mixins = {}) self.schema = Schema.new(name, options) self.mixins = mixins end # Creates an attribute and saving it into the schema. # It uses the same parameters as the {Attribute#initialize} method. # # @example # # schema :books do # attribute :title, string # attribute :created_at, datetime, :for => [:response] # end # # @param (see Attribute#initialize) def attribute(name, type, options = {}) new_attribute = Attribute.new(name, type, options) schema.attributes[name.to_s] = new_attribute end # Includes a mixin generated by the {DSL#mixin} function # into the schema. # # @example (see DSL#mixin) # # @param name [Symbol] the mixin name def include_attributes(name) self.instance_eval &mixins.fetch(name) end private attr_writer :schema attr_accessor :mixins end end end