module Validate::Constraint::DSL

Public Class Methods

common_options() click to toggle source
# File lib/validate/constraint.rb, line 77
def common_options
  @common_options ||= {
      message: Option.new(:message, default: 'be %{constraint.name}') do
        not_blank
        is_a(String)
      end
  }.freeze
end
constraint_name() click to toggle source
# File lib/validate/constraint.rb, line 69
def constraint_name
  @constraint_name ||= Assertions.create do
    not_nil(message: 'constraint name must not be nil')
    is_a(Symbol, message: 'constraint name must be a Symbol')
  end
end
new(&initialize_block) click to toggle source
Calls superclass method
# File lib/validate/constraint.rb, line 108
def initialize(&initialize_block)
  supported_options = @supported_options
  expects_kwargs = false
  initialize_block.parameters.each do |(kind, name)|
    if %i(keyreq key).include?(kind) && supported_options.include?(name)
      raise Error::ArgumentError,
            "key name #{name}: conflicts with an existing option"
    end
    expects_kwargs = true if kind == :keyrest
  end

  define_constraint_method(:initialize, initialize_block) do |*args, &block|
    if args.last.is_a?(Hash)
      known_options, kwargs =
          args.pop
              .partition { |k, _| supported_options.include?(k) }
              .map { |h| Hash[h] }

      if !expects_kwargs && !kwargs.empty?
        args << kwargs
        kwargs = {}
      end

      if expects_kwargs
        merged_options = {}.merge!(super(*args, **kwargs, &block), known_options)
      else
        args << kwargs unless kwargs.empty?
        merged_options = {}.merge!(super(*args, &block), known_options)
      end
    else
      merged_options = super(*args, &block)
    end

    options = supported_options.each_with_object({}) do |(n, opt), opts|
      opts[n] = opt.get_or_default(merged_options)
    end

    unless merged_options.empty?
      raise Error::ArgumentError,
            "unexpected options #{merged_options.inspect}"
    end

    @options = options.freeze
  end
  remove_instance_variable(:@supported_options)
end

Public Instance Methods

describe(&describe_block) click to toggle source
# File lib/validate/constraint.rb, line 165
def describe(&describe_block)
  define_method(:to_s, &describe_block)
  self
end
evaluate(&validation_block) click to toggle source
Calls superclass method
# File lib/validate/constraint.rb, line 155
def evaluate(&validation_block)
  define_constraint_method(:valid?, validation_block) do |*args|
    catch(:result) do
      super(*args[0...validation_block.arity])
      :pass
    end == :pass
  end
  self
end
key(&key_block) click to toggle source
# File lib/validate/constraint.rb, line 170
def key(&key_block)
  define_method(:name, &key_block)
  self
end
option( name, default: lambda do raise Error::KeyError, "option click to toggle source
# File lib/validate/constraint.rb, line 87
def option(
    name,
    default: lambda do
      raise Error::KeyError,
            "option #{name.inspect} is required for #{self.name}"
    end,
    &assert_block
)
  constraint_name.assert(name)
  if @supported_options.include?(name)
    raise Error::ArgumentError, "duplicate option :#{name}"
  end

  @supported_options[name] = Option.new(
      name,
      default: default,
      &assert_block
  )
  self
end

Private Instance Methods

common_options() click to toggle source
# File lib/validate/constraint.rb, line 77
def common_options
  @common_options ||= {
      message: Option.new(:message, default: 'be %{constraint.name}') do
        not_blank
        is_a(String)
      end
  }.freeze
end
constraint_name() click to toggle source
# File lib/validate/constraint.rb, line 69
def constraint_name
  @constraint_name ||= Assertions.create do
    not_nil(message: 'constraint name must not be nil')
    is_a(Symbol, message: 'constraint name must be a Symbol')
  end
end
define_constraint_method(name, body, &override) click to toggle source
# File lib/validate/constraint.rb, line 177
def define_constraint_method(name, body, &override)
  @constraint_user_methods.__send__(:define_method, name, &body)
  define_method(name, &override)
  self
end