lib/datacaster/predefined.rb in datacaster-2.0.2 vs lib/datacaster/predefined.rb in datacaster-3.0.0
- old
+ new
@@ -2,77 +2,98 @@
module Predefined
extend self
# Base types
- def cast(name = 'Anonymous', &block)
- Caster.new(name, &block)
+ def cast(&block)
+ Caster.new(&block)
end
- def check(name = 'Anonymous', error = 'is invalid', &block)
- Checker.new(name, error, &block)
+ def check(error_key = nil, &block)
+ Checker.new(error_key, &block)
end
- def compare(value, name = 'Anonymous', error = nil)
- Comparator.new(value, name, error)
+ def compare(value, error_key = nil)
+ Comparator.new(value, error_key)
end
- def transform(name = 'Anonymous', &block)
- Transformer.new(name, &block)
+ def transform(&block)
+ Transformer.new(&block)
end
- def transform_if_present(name = 'Anonymous', &block)
+ def transform_if_present(&block)
raise 'Expected block' unless block_given?
- Transformer.new(name) { |v| v == Datacaster.absent ? v : block.(v) }
+ Transformer.new { |v| v == Datacaster.absent ? v : block.(v) }
end
- def try(name = 'Anonymous', error = 'is invalid', catched_exception:, &block)
- Trier.new(name, error, catched_exception, &block)
+ def try(error_key = nil, catched_exception:, &block)
+ Trier.new(catched_exception, error_key, &block)
end
- def array_schema(element_caster)
- ArraySchema.new(element_caster)
+ def array_schema(element_caster, error_keys = {})
+ ArraySchema.new(DefinitionDSL.expand(element_caster), error_keys)
end
alias_method :array_of, :array_schema
- def hash_schema(fields)
- HashSchema.new(fields)
+ def hash_schema(fields, error_key = nil)
+ unless fields.is_a?(Hash)
+ raise "Expected field definitions in a form of Hash for hash_schema, got #{fields.inspect} instead"
+ end
+ HashSchema.new(
+ fields.transform_values { |f| DefinitionDSL.expand(f) },
+ error_key
+ )
end
def transform_to_hash(fields)
- HashMapper.new(fields)
+ HashMapper.new(fields.transform_values { |x| DefinitionDSL.expand(x) })
end
- def validate(active_model_validations, name = 'Anonymous')
- Validator.new(active_model_validations, name)
+ def validate(active_model_validations)
+ Validator.new(active_model_validations)
end
# 'Meta' types
- def absent
- check('Absent', 'must be absent') { |x| x == Datacaster.absent }
+ def absent(error_key = nil)
+ error_keys = ['.absent', 'datacaster.errors.absent']
+ error_keys.unshift(error_key) if error_key
+ check { |x| x == Datacaster.absent }.i18n_key(*error_keys)
end
- def any
- check('Any', 'must be set') { |x| x != Datacaster.absent }
+ def any(error_key = nil)
+ error_keys = ['.any', 'datacaster.errors.any']
+ error_keys.unshift(error_key) if error_key
+ check { |x| x != Datacaster.absent }.i18n_key(*error_keys)
end
+ def default(value, on: nil)
+ transform do |x|
+ if x == Datacaster.absent ||
+ (on && x.respond_to?(on) && x.public_send(on))
+ value
+ else
+ x
+ end
+ end
+ end
+
def transform_to_value(value)
- transform('ToValue') { value }
+ transform { value }
end
def remove
- transform('Remove') { Datacaster.absent }
+ transform { Datacaster.absent }
end
def pass
- transform('Pass', &:itself)
+ transform(&:itself)
end
def pick(*keys)
- must_be(Enumerable) & transform("Picker") { |value|
+ must_be(Enumerable) & transform { |value|
result =
keys.map do |key|
if value.respond_to?(:key?) && !value.key?(key)
Datacaster.absent
elsif value.respond_to?(:length) && key.is_a?(Integer) && key > 0 && key >= value.length
@@ -88,97 +109,131 @@
def merge_message_keys(*keys)
MessageKeysMerger.new(keys)
end
- def responds_to(method)
- check('RespondsTo', "must respond to #{method.inspect}") { |x| x.respond_to?(method) }
+ def responds_to(method, error_key = nil)
+ error_keys = ['.responds_to', 'datacaster.errors.responds_to']
+ error_keys.unshift(error_key) if error_key
+ check { |x| x.respond_to?(method) }.i18n_key(*error_keys, reference: method.to_s)
end
- def must_be(klass)
- check('MustBe', "must be #{klass.inspect}") { |x| x.is_a?(klass) }
+ def must_be(klass, error_key = nil)
+ error_keys = ['.must_be', 'datacaster.errors.must_be']
+ error_keys.unshift(error_key) if error_key
+ check { |x| x.is_a?(klass) }.i18n_key(*error_keys, reference: klass.name)
end
def optional(base)
absent | base
end
# Strict types
- def decimal(digits = 8)
- Trier.new('Decimal', 'must be decimal', [ArgumentError, TypeError]) do |x|
+ def decimal(digits = 8, error_key = nil)
+ error_keys = ['.decimal', 'datacaster.errors.decimal']
+ error_keys.unshift(error_key) if error_key
+
+ Trier.new([ArgumentError, TypeError]) do |x|
# strictly validate format of string, BigDecimal() doesn't do that
Float(x)
BigDecimal(x, digits)
- end
+ end.i18n_key(*error_keys)
end
- def array
- check('Array', 'must be array') { |x| x.is_a?(Array) }
+ def array(error_key = nil)
+ error_keys = ['.array', 'datacaster.errors.array']
+ error_keys.unshift(error_key) if error_key
+ check { |x| x.is_a?(Array) }.i18n_key(*error_keys)
end
- def float
- check('Float', 'must be float') { |x| x.is_a?(Float) }
+ def float(error_key = nil)
+ error_keys = ['.float', 'datacaster.errors.float']
+ error_keys.unshift(error_key) if error_key
+ check { |x| x.is_a?(Float) }.i18n_key(*error_keys)
end
- # 'hash' is a bad method name, because it will overwrite built in Object#hash
- def hash_value
- check('Hash', 'must be hash') { |x| x.is_a?(Hash) }
+ # 'hash' would be a bad method name, because it would override built in Object#hash
+ def hash_value(error_key = nil)
+ error_keys = ['.hash_value', 'datacaster.errors.hash_value']
+ error_keys.unshift(error_key) if error_key
+ check(error_key) { |x| x.is_a?(Hash) }
end
- def hash_with_symbolized_keys
- hash_value & transform("SymbolizeKeys") { |x| x.symbolize_keys }
+ def hash_with_symbolized_keys(error_key = nil)
+ hash_value(error_key) & transform { |x| x.symbolize_keys }
end
- def integer
- check('Integer', 'must be integer') { |x| x.is_a?(Integer) }
+ def integer(error_key = nil)
+ error_keys = ['.integer', 'datacaster.errors.integer']
+ error_keys.unshift(error_key) if error_key
+ check { |x| x.is_a?(Integer) }.i18n_key(*error_keys)
end
- def integer32
- integer & check('FourBytes', 'out of range') { |x| x.abs <= 2_147_483_647 }
+ def integer32(error_key = nil)
+ error_keys = ['.integer32', 'datacaster.errors.integer32']
+ error_keys.unshift(error_key) if error_key
+ integer(error_key) & check { |x| x.abs <= 2_147_483_647 }.i18n_key(*error_keys)
end
- def string
- check('String', 'must be string') { |x| x.is_a?(String) }
+ def string(error_key = nil)
+ error_keys = ['.string', 'datacaster.errors.string']
+ error_keys.unshift(error_key) if error_key
+ check { |x| x.is_a?(String) }.i18n_key(*error_keys)
end
- def non_empty_string
- string & check('NonEmptyString', 'must be present') { |x| !x.empty? }
+ def non_empty_string(error_key = nil)
+ error_keys = ['.non_empty_string', 'datacaster.errors.non_empty_string']
+ error_keys.unshift(error_key) if error_key
+ string(error_key) & check { |x| !x.empty? }.i18n_key(*error_keys)
end
# Form request types
- def iso8601
- string &
- try('ISO8601', 'must be iso8601 string', catched_exception: [ArgumentError, TypeError]) { |x| DateTime.iso8601(x) }
+ def iso8601(error_key = nil)
+ error_keys = ['.iso8601', 'datacaster.errors.iso8601']
+ error_keys.unshift(error_key) if error_key
+
+ string(error_key) &
+ try(catched_exception: [ArgumentError, TypeError]) { |x| DateTime.iso8601(x) }.
+ i18n_key(*error_keys)
end
- def to_boolean
- cast('ToBoolean') do |x|
+ def to_boolean(error_key = nil)
+ error_keys = ['.to_boolean', 'datacaster.errors.to_boolean']
+ error_keys.unshift(error_key) if error_key
+
+ cast do |x|
if ['true', '1', true].include?(x)
Datacaster.ValidResult(true)
elsif ['false', '0', false].include?(x)
Datacaster.ValidResult(false)
else
- Datacaster.ErrorResult(['must be boolean'])
+ Datacaster.ErrorResult(Datacaster::I18nValues::Key.new(error_keys, value: x))
end
end
end
- def to_float
- Trier.new('ToFloat', 'must be float', [ArgumentError, TypeError]) do |x|
+ def to_float(error_key = nil)
+ error_keys = ['.to_float', 'datacaster.errors.to_float']
+ error_keys.unshift(error_key) if error_key
+
+ Trier.new([ArgumentError, TypeError]) do |x|
Float(x)
- end
+ end.i18n_key(*error_keys)
end
- def to_integer
- Trier.new('ToInteger', 'must be integer', [ArgumentError, TypeError]) do |x|
+ def to_integer(error_key = nil)
+ error_keys = ['.to_integer', 'datacaster.errors.to_integer']
+ error_keys.unshift(error_key) if error_key
+
+ Trier.new([ArgumentError, TypeError]) do |x|
Integer(x)
- end
+ end.i18n_key(*error_keys)
end
def optional_param(base)
- transform_if_present("optional_param(#{base.inspect})") { |x| x == '' ? Datacaster::Absent.instance : x } & (absent | base)
+ transform_if_present { |x| x == '' ? Datacaster::Absent.instance : x } & (absent | base)
end
end
end