lib/dry/data.rb in dry-data-0.2.1 vs lib/dry/data.rb in dry-data-0.3.0

- old
+ new

@@ -2,19 +2,24 @@ require 'date' require 'set' require 'dry-container' require 'inflecto' +require 'thread_safe/cache' require 'dry/data/version' require 'dry/data/container' require 'dry/data/type' require 'dry/data/struct' require 'dry/data/dsl' module Dry module Data + extend Dry::Configurable + + setting :namespace, self + class SchemaError < TypeError def initialize(key, value) super("#{value.inspect} (#{value.class}) has invalid type for :#{key}") end end @@ -24,13 +29,18 @@ super(":#{key} is missing in Hash input") end end StructError = Class.new(TypeError) + ConstraintError = Class.new(TypeError) TYPE_SPEC_REGEX = %r[(.+)<(.+)>].freeze + def self.finalize + define_constants(config.namespace, container._container.keys) + end + def self.container @container ||= Container.new end def self.register(name, type = nil, &block) @@ -43,11 +53,11 @@ Type.new(klass.method(:new), klass) ) end def self.[](name) - type_map.fetch(name) do + type_map.fetch_or_store(name) do result = name.match(TYPE_SPEC_REGEX) type = if result type_id, member_id = result[1..2] @@ -58,16 +68,35 @@ type_map[name] = type end end + 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 + + def self.identifier(klass) + Inflecto.underscore(klass).gsub('/', '.') + end + def self.type(*args, &block) dsl = DSL.new(container) block ? yield(dsl) : registry[args.first] end def self.type_map - @type_map ||= {} + @type_map ||= ThreadSafe::Cache.new end end end require 'dry/data/types' # load built-in types