Module: Dry::Data

Extended by:
Configurable
Defined in:
lib/dry/data.rb,
lib/dry/data/dsl.rb,
lib/dry/data/type.rb,
lib/dry/data/types.rb,
lib/dry/data/value.rb,
lib/dry/data/struct.rb,
lib/dry/data/version.rb,
lib/dry/data/compiler.rb,
lib/dry/data/sum_type.rb,
lib/dry/data/container.rb,
lib/dry/data/type/enum.rb,
lib/dry/data/type/hash.rb,
lib/dry/data/type/array.rb,
lib/dry/data/types/form.rb,
lib/dry/data/constraints.rb,
lib/dry/data/type/optional.rb,
lib/dry/data/coercions/form.rb,
lib/dry/data/type/constrained.rb

Defined Under Namespace

Modules: Coercions Classes: Compiler, Container, DSL, SchemaError, SchemaKeyError, Struct, SumType, Type, Value

Constant Summary collapse

StructError =
Class.new(TypeError)
ConstraintError =
Class.new(TypeError)
TYPE_SPEC_REGEX =
%r[(.+)<(.+)>].freeze
COERCIBLE =
{
  string: String,
  int: Integer,
  float: Float,
  decimal: BigDecimal,
  array: Array,
  hash: Hash
}.freeze
NON_COERCIBLE =
{
  nil: NilClass,
  symbol: Symbol,
  class: Class,
  true: TrueClass,
  false: FalseClass,
  date: Date,
  date_time: DateTime,
  time: Time
}.freeze
ALL_PRIMITIVES =
COERCIBLE.merge(NON_COERCIBLE).freeze
VERSION =
'0.3.2'.freeze

Class Method Summary collapse

Class Method Details

.[](name) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/dry/data.rb', line 60

def self.[](name)
  type_map.fetch_or_store(name) do
    result = name.match(TYPE_SPEC_REGEX)

    type =
      if result
        type_id, member_id = result[1..2]
        container[type_id].member(self[member_id])
      else
        container[name]
      end

    type_map[name] = type
  end
end

.containerObject



45
46
47
# File 'lib/dry/data.rb', line 45

def self.container
  @container ||= Container.new
end

.define_constants(namespace, identifiers) ⇒ Object



76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/dry/data.rb', line 76

def self.define_constants(namespace, identifiers)
  names = identifiers.map do |id|
    parts = id.split('.')
    [Inflecto.camelize(parts.pop), parts.map(&Inflecto.method(:camelize))]
  end

  names.map do |(klass, parts)|
    mod = parts.reduce(namespace) do |a, e|
      a.constants.include?(e.to_sym) ? a.const_get(e) : a.const_set(e, Module.new)
    end

    mod.const_set(klass, self[identifier((parts + [klass]).join('::'))])
  end
end

.finalizeObject



41
42
43
# File 'lib/dry/data.rb', line 41

def self.finalize
  define_constants(config.namespace, container._container.keys)
end

.identifier(klass) ⇒ Object



91
92
93
# File 'lib/dry/data.rb', line 91

def self.identifier(klass)
  Inflecto.underscore(klass).gsub('/', '.')
end

.register(name, type = nil, &block) ⇒ Object



49
50
51
# File 'lib/dry/data.rb', line 49

def self.register(name, type = nil, &block)
  container.register(name, type || block.call)
end

.register_class(klass) ⇒ Object



53
54
55
56
57
58
# File 'lib/dry/data.rb', line 53

def self.register_class(klass)
  container.register(
    Inflecto.underscore(klass).gsub('/', '.'),
    Type.new(klass.method(:new), klass)
  )
end

.Rule(primitive, options) ⇒ Object



6
7
8
9
10
11
12
# File 'lib/dry/data/constraints.rb', line 6

def self.Rule(primitive, options)
  rule_compiler.(
    options.map { |key, val|
      [:val, [primitive, [:predicate, [:"#{key}?", [val]]]]]
    }
  ).reduce(:and)
end

.rule_compilerObject



14
15
16
# File 'lib/dry/data/constraints.rb', line 14

def self.rule_compiler
  @rule_compiler ||= Validation::RuleCompiler.new(Validation::Predicates)
end

.SumType(left, right) ⇒ Object



5
6
7
8
9
10
11
12
13
# File 'lib/dry/data/sum_type.rb', line 5

def self.SumType(left, right)
  klass =
    if left.is_a?(Type::Optional)
      SumType::Optional
    else
      SumType
    end
  klass.new(left, right)
end

.type(*args, &block) ⇒ Object



95
96
97
98
# File 'lib/dry/data.rb', line 95

def self.type(*args, &block)
  dsl = DSL.new(container)
  block ? yield(dsl) : registry[args.first]
end

.type_mapObject



100
101
102
# File 'lib/dry/data.rb', line 100

def self.type_map
  @type_map ||= ThreadSafe::Cache.new
end