module Dry::Validation::Contract::ClassInterface
Contract's class interface
@see Contract
@api public
Public Instance Methods
@api private
# File lib/dry/validation/contract/class_interface.rb, line 130 def __schema__ @__schema__ if defined?(@__schema__) end
A shortcut that can be used to define contracts that won't be reused or inherited
@example
my_contract = Dry::Validation::Contract.build do params do required(:name).filled(:string) end end my_contract.call(name: "Jane")
@return [Contract]
@api public
# File lib/dry/validation/contract/class_interface.rb, line 125 def build(options = EMPTY_HASH, &block) Class.new(self, &block).new(**options) end
Configuration
@example
class MyContract < Dry::Validation::Contract config.messages.backend = :i18n end
@return [Config]
@api public
# File lib/dry/validation/contract/class_interface.rb, line 39 def config @config ||= Validation::Config.new end
@api private
# File lib/dry/validation/contract/class_interface.rb, line 24 def inherited(klass) super klass.instance_variable_set("@config", config.dup) end
Define a JSON schema for your contract
This type of schema is suitable for JSON data
@return [Dry::Schema::JSON,NilClass] @see dry-rb.org/gems/dry-schema/json/
@api public
# File lib/dry/validation/contract/class_interface.rb, line 72 def json(*external_schemas, &block) define(:JSON, external_schemas, &block) end
Return macros registered for this class
@return [Macros::Container]
@api public
# File lib/dry/validation/contract/class_interface.rb, line 48 def macros config.macros end
Return messages configured for this class
@return [Dry::Schema::Messages]
@api private
# File lib/dry/validation/contract/class_interface.rb, line 150 def messages @messages ||= Schema::Messages.setup(config.messages) end
Define a params schema for your contract
This type of schema is suitable for HTTP parameters
@return [Dry::Schema::Params,NilClass] @see dry-rb.org/gems/dry-schema/params/
@api public
# File lib/dry/validation/contract/class_interface.rb, line 60 def params(*external_schemas, &block) define(:Params, external_schemas, &block) end
Define a rule for your contract
@example using a symbol
rule(:age) do failure('must be at least 18') if values[:age] < 18 end
@example using a path to a value and a custom predicate
rule('address.street') do failure('please provide a valid street address') if valid_street?(values[:street]) end
@return [Rule]
@api public
# File lib/dry/validation/contract/class_interface.rb, line 103 def rule(*keys, &block) ensure_valid_keys(*keys) if __schema__ Rule.new(keys: keys, block: block).tap do |rule| rules << rule end end
Return rules defined in this class
@return [Array<Rule>]
@api private
# File lib/dry/validation/contract/class_interface.rb, line 139 def rules @rules ||= EMPTY_ARRAY .dup .concat(superclass.respond_to?(:rules) ? superclass.rules : EMPTY_ARRAY) end
Define a plain schema for your contract
This type of schema does not offer coercion out of the box
@return [Dry::Schema::Processor,NilClass] @see dry-rb.org/gems/dry-schema/
@api public
# File lib/dry/validation/contract/class_interface.rb, line 84 def schema(*external_schemas, &block) define(:schema, external_schemas, &block) end
Private Instance Methods
@api private
# File lib/dry/validation/contract/class_interface.rb, line 202 def core_schema_opts {parent: superclass&.__schema__, config: config} end
@api private
# File lib/dry/validation/contract/class_interface.rb, line 207 def define(method_name, external_schemas, &block) return __schema__ if external_schemas.empty? && block.nil? unless __schema__.nil? raise ::Dry::Validation::DuplicateSchemaError, "Schema has already been defined" end schema_opts = core_schema_opts schema_opts.update(parent: external_schemas) if external_schemas.any? case method_name when :schema @__schema__ = Schema.define(**schema_opts, &block) when :Params @__schema__ = Schema.Params(**schema_opts, &block) when :JSON @__schema__ = Schema.JSON(**schema_opts, &block) end end
@api private
# File lib/dry/validation/contract/class_interface.rb, line 157 def ensure_valid_keys(*keys) valid_paths = key_map.to_dot_notation key_paths = key_paths(keys) invalid_keys = key_paths.map { |(key, path)| unless valid_paths.any? { |vp| vp.include?(path) || vp.include?("#{path}[]") } key end }.compact.uniq return if invalid_keys.empty? raise InvalidKeysError, <<~STR.strip #{name}.rule specifies keys that are not defined by the schema: #{invalid_keys.inspect} STR end
@api private
# File lib/dry/validation/contract/class_interface.rb, line 197 def key_map __schema__.key_map end
@api private
# File lib/dry/validation/contract/class_interface.rb, line 175 def key_paths(keys) keys.map { |key| case key when Hash path = Schema::Path[key] if path.multi_value? *head, tail = Array(path) [key].product( tail.map { |el| [*head, *el] }.map { |parts| parts.join(DOT) } ) else [[key, path.to_a.join(DOT)]] end when Array [[key, Schema::Path[key].to_a.join(DOT)]] else [[key, key.to_s]] end }.flatten(1) end