Skip to content

Instantly share code, notes, and snippets.

@AMHOL AMHOL/dry-validator.rb Secret
Last active Aug 29, 2015

Embed
What would you like to do?
require 'thread_safe'
require 'dry-configurable'
require 'dry/validator/version'
# A collection of micro-libraries, each intended to encapsulate
# a common task in Ruby
module Dry
# A simple stand-alone validator
#
# @example
#
# User = Struct.new(:name)
#
# user_validator = Dry::Validator.new(
# name: {
# presence: true
# }
# )
#
# user = User.new('')
# validator.call(user)
# => {:name=>[{:code=>"presence", :options=>true}]}
#
# @api public
class Validator
attr_reader :rules, :processor
setting :default_processor, Dry::Validator::Processor
def initialize(**params)
if params.fetch(:rules, false)
@rules = params.fetch(:rules, {})
@processor = params.fetch(:processor, default_processor)
else
@rules = params
@processor = default_processor
end
end
def merge(other)
self.class.new(
rules: rules.merge(other.rules),
processor: processor
)
end
alias_method :<<, :merge
def call(attributes)
processor.call(rules, attributes)
end
alias_method :validate, :call
private
def default_processor
self.class.config.default_processor
end
end
end
@AMHOL

This comment has been minimized.

Copy link
Owner Author

AMHOL commented Jul 22, 2015

require 'thread_safe'
require 'dry-configurable'
require 'dry/validator/version'

# A collection of micro-libraries, each intended to encapsulate
# a common task in Ruby
module Dry
  # A simple stand-alone validator
  #
  # @example
  #
  #   User = Struct.new(:name)
  #
  #   user_validator = Dry::Validator.new(
  #     name: {
  #       presence: true
  #     }
  #   )
  #
  #   user = User.new('Jack')
  #   validator.call(user) 
  #     => {:name=>[{:code=>"presence", :options=>true}]}
  #
  # @api public
  class Validator
    attr_reader :rules, :processor, :extractor

    setting :default_processor, ->(*args) { Dry::Validations[*args] }
    setting :default_extractor, ->(attributes, attribute_name) { attributes[attribute_name] }

    def initialize(**params)
      if params.fetch(:rules, false)
        @rules = params.fetch(:rules, {})
        @extractor = params.fetch(:extractor, default_extractor)
        @processor = params.fetch(:processor, default_processor)
      else
        @rules = params
        @extractor = default_extractor
        @processor = default_processor
      end
    end

    def merge(other)
      self.class.new(
        rules: rules.merge(other.rules),
        extractor: extractor,
        processor: processor
      )
    end
    alias_method :<<, :merge

    def call(attributes)
      rules.each_with_object({}) do |(attribute_name, rule_set), result|
        errors = rule_set.map do |rule_name, options|
          processor.call(rule_name, options).call(
            extractor.call(attributes, attribute_name)
          )
        end.compact

        result[attribute_name] = errors unless errors.empty?
      end
    end
    alias_method :validate, :call

    private

    def default_processor
      self.class.config.default_processor
    end

    def default_extractor
      self.class.config.default_extractor
    end
  end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.