Class: Dry::Schema::DSL

Inherits:
Object
  • Object
show all
Extended by:
Initializer
Defined in:
lib/dry/schema/dsl.rb

Overview

The schema definition DSL class

The DSL is exposed by:

- `Schema.define`
- `Schema.Params`
- `Schema.JSON`
- `Schema::Params.define` - use with sub-classes
- `Schema::JSON.define` - use with sub-classes

Examples:

class-based definition

class UserSchema < Dry::Schema::Params
  define do
    required(:name).filled
    required(:age).filled(:integer, gt: 18)
  end
end

user_schema = UserSchema.new
user_schema.(name: 'Jame', age: 21)

instance-based definition shortcut

UserSchema = Dry::Schema.Params do
  required(:name).filled
  required(:age).filled(:integer, gt: 18)
end

UserSchema.(name: 'Jame', age: 21)

Constant Summary collapse

Types =
Schema::Types

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.new(**options, &block) ⇒ DSL

Build a new DSL object and evaluate provided block

Parameters:

  • options (Hash)

Options Hash (**options):

  • :processor (Class)

    The processor type (‘Params`, `JSON` or a custom sub-class)

  • :compiler (Compiler)

    An instance of a rule compiler (must be compatible with ‘Schema::Compiler`) (optional)

  • :parent (DSL)

    An instance of the parent DSL (optional)

  • :config (Config)

    A configuration object (optional)

Returns:

See Also:



89
90
91
92
93
# File 'lib/dry/schema/dsl.rb', line 89

def self.new(**options, &block)
  dsl = super
  dsl.instance_eval(&block) if block
  dsl
end

Instance Method Details

#[](name) ⇒ Macros::Core

Return a macro with the provided name

Parameters:

  • name (Symbol)

Returns:



121
122
123
# File 'lib/dry/schema/dsl.rb', line 121

def [](name)
  macros.detect { |macro| macro.name.equal?(name) }
end

#arrayDry::Types::Array::Member

A shortcut for defining an array type with a member

Examples:

required(:tags).filled(array[:string])

Returns:

  • (Dry::Types::Array::Member)


214
215
216
# File 'lib/dry/schema/dsl.rb', line 214

def array
  -> member_type { type_registry['array'].of(resolve_type(member_type)) }
end

#callProcessor, ...

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Build a processor based on DSL’s definitions

Returns:



191
192
193
194
195
196
197
# File 'lib/dry/schema/dsl.rb', line 191

def call
  steps = [key_coercer]
  steps << filter_schema.rule_applier if filter_rules?
  steps << value_coercer << rule_applier

  processor_type.new(schema_dsl: self, steps: steps)
end

#compilerCompiler

Returns The rule compiler object.

Returns:

  • (Compiler)

    The rule compiler object



56
# File 'lib/dry/schema/dsl.rb', line 56

option :compiler, default: -> { Compiler.new }

#configConfig

Returns Configuration object exposed via ‘#configure` method.

Returns:

  • (Config)

    Configuration object exposed via ‘#configure` method



71
# File 'lib/dry/schema/dsl.rb', line 71

option :config, optional: true, default: proc { parent ? parent.config.dup : Config.new }

#configure(&block) ⇒ DSL

Provide customized configuration for your schema

Examples:

Dry::Schema.define do
  configure do |config|
    config.messages.backend = :i18n
  end
end

Returns:

See Also:



109
110
111
112
# File 'lib/dry/schema/dsl.rb', line 109

def configure(&block)
  config.configure(&block)
  self
end

#filter_rules?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Check if any filter rules were defined

Returns:

  • (Boolean)


285
286
287
# File 'lib/dry/schema/dsl.rb', line 285

def filter_rules?
  (instance_variable_defined?('@filter_schema_dsl') && !filter_schema_dsl.macros.empty?) || parent&.filter_rules?
end

#filter_schemaObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



269
270
271
# File 'lib/dry/schema/dsl.rb', line 269

def filter_schema
  filter_schema_dsl.call
end

#filter_schema_dslObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Build an input schema DSL used by ‘filter` API

See Also:

  • Macros::Value#filter


278
279
280
# File 'lib/dry/schema/dsl.rb', line 278

def filter_schema_dsl
  @filter_schema_dsl ||= new(parent: parent_filter_schema)
end

#key(name, macro:, &block) ⇒ Macros::Key

A generic method for defining keys

Parameters:

  • name (Symbol)

    The key name

  • macro (Class)

    The macro sub-class (ie ‘Macros::Required` or any other `Macros::Key` subclass)

Returns:

Raises:

  • (ArgumentError)


169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/dry/schema/dsl.rb', line 169

def key(name, macro:, &block)
  raise ArgumentError, "Key +#{name}+ is not a symbol" unless name.is_a?(::Symbol)

  set_type(name, Types::Any)

  macro = macro.new(
    name: name,
    compiler: compiler,
    schema_dsl: self,
    filter_schema_dsl: filter_schema_dsl
  )

  macro.value(&block) if block
  macros << macro
  macro
end

#macrosArray

Returns An array with macros defined within the DSL.

Returns:

  • (Array)

    An array with macros defined within the DSL



62
# File 'lib/dry/schema/dsl.rb', line 62

option :macros, default: -> { EMPTY_ARRAY.dup }

#new(options = EMPTY_HASH, &block) ⇒ Dry::Types::Safe

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Return a new DSL instance using the same processor type

Returns:

  • (Dry::Types::Safe)


233
234
235
# File 'lib/dry/schema/dsl.rb', line 233

def new(options = EMPTY_HASH, &block)
  self.class.new(options.merge(processor_type: processor_type, config: config), &block)
end

#optional(name, &block) ⇒ Macros::Optional

Define an optional key

This works exactly the same as ‘required` except that if a key is not present rules will not be applied

Parameters:

  • name (Symbol)

    The key name

Returns:

See Also:



157
158
159
# File 'lib/dry/schema/dsl.rb', line 157

def optional(name, &block)
  key(name, macro: Macros::Optional, &block)
end

#parentDSL

Returns An optional parent DSL object that will be used to merge keys and rules.

Returns:

  • (DSL)

    An optional parent DSL object that will be used to merge keys and rules



68
# File 'lib/dry/schema/dsl.rb', line 68

option :parent, optional: true

#processor_typeCompiler

Returns The type of the processor (Params, JSON, or a custom sub-class).

Returns:

  • (Compiler)

    The type of the processor (Params, JSON, or a custom sub-class)



59
# File 'lib/dry/schema/dsl.rb', line 59

option :processor_type, default: -> { Processor }

#required(name, &block) ⇒ Macros::Required

Define a required key

Examples:

required(:name).filled

required(:age).value(:integer)

required(:user_limit).value(:integer, gt?: 0)

required(:tags).filled { array? | str? }

Parameters:

  • name (Symbol)

    The key name

Returns:



141
142
143
# File 'lib/dry/schema/dsl.rb', line 141

def required(name, &block)
  key(name, macro: Macros::Required, &block)
end

#resolve_type(spec) ⇒ Dry::Types::Type

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Resolve type object from the provided spec

Parameters:

  • spec (Symbol, Array<Symbol>, Dry::Types::Type)

Returns:

  • (Dry::Types::Type)


259
260
261
262
263
264
265
266
# File 'lib/dry/schema/dsl.rb', line 259

def resolve_type(spec)
  case spec
  when ::Dry::Types::Type then spec
  when ::Array then spec.map { |s| resolve_type(s) }.reduce(:|)
  else
    type_registry[spec]
  end
end

#set_type(name, spec) ⇒ Dry::Types::Safe

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Set a type for the given key name

Parameters:

  • name (Symbol)

    The key name

  • spec (Symbol, Array<Symbol>, Dry::Types::Type)

    The type spec or a type object

Returns:

  • (Dry::Types::Safe)


245
246
247
248
249
250
# File 'lib/dry/schema/dsl.rb', line 245

def set_type(name, spec)
  type = resolve_type(spec)
  meta = { required: false, maybe: type.optional? }

  types[name] = type.meta(meta)
end

#to_ruleRuleApplier

Cast this DSL into a rule object

Returns:



202
203
204
# File 'lib/dry/schema/dsl.rb', line 202

def to_rule
  call.to_rule
end

#type_schemaDry::Types::Safe

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Return type schema used by the value coercer

Returns:

  • (Dry::Types::Safe)


223
224
225
226
# File 'lib/dry/schema/dsl.rb', line 223

def type_schema
  schema = type_registry['hash'].schema(types).lax
  parent ? parent.type_schema.schema(schema.to_a) : schema
end

#typesCompiler

Returns A key=>type map defined within the DSL.

Returns:

  • (Compiler)

    A key=>type map defined within the DSL



65
# File 'lib/dry/schema/dsl.rb', line 65

option :types, default: -> { EMPTY_HASH.dup }