Skip to content

Commit

Permalink
Specs
Browse files Browse the repository at this point in the history
  • Loading branch information
EugZol committed Sep 22, 2023
1 parent 49d94eb commit 4c259a3
Show file tree
Hide file tree
Showing 27 changed files with 287 additions and 163 deletions.
2 changes: 1 addition & 1 deletion config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ en:
hash_value: is not a hash
integer: is not an integer
integer32: is not a 32-bit integer
iso8601: is not a string with ISO-8601 date
iso8601: is not a string with ISO-8601 date and time
must_be: "is not %{reference}"
responds_to: "does not respond to %{reference}"
string: is not a string
Expand Down
2 changes: 1 addition & 1 deletion lib/datacaster/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def with_context(context)
end

def call(object)
call_with_runtime(object, Runtime.new)
call_with_runtime(object, Runtimes::Base.new)
end

def call_with_runtime(object, runtime)
Expand Down
2 changes: 1 addition & 1 deletion lib/datacaster/caster.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ def initialize(&block)
end

def cast(object, runtime:)
result = Runtime.(runtime, @cast, object)
result = Runtimes::Base.(runtime, @cast, object)

raise TypeError.new("Either Datacaster::Result or Dry::Monads::Result " \
"should be returned from cast block") unless [Datacaster::Result, Dry::Monads::Result].any? { |k| result.is_a?(k) }
Expand Down
2 changes: 1 addition & 1 deletion lib/datacaster/checker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ def initialize(&block)
end

def cast(object, runtime:)
if Runtime.(runtime, @check, object)
if Runtimes::Base.(runtime, @check, object)
Datacaster.ValidResult(object)
else
Datacaster.ErrorResult(I18nValues::DefaultKeys.new(['.check', 'datacaster.errors.check'], value: object))
Expand Down
2 changes: 1 addition & 1 deletion lib/datacaster/comparator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ def cast(object, runtime:)
Datacaster.ValidResult(object)
else
Datacaster.ErrorResult(
I18nValues::DefaultKeys.new(['.compare', 'datacaster.errors.compare'], reference: value, value: object)
I18nValues::DefaultKeys.new(['.compare', 'datacaster.errors.compare'], reference: @value.inspect, value: object)
)
end
end
Expand Down
19 changes: 16 additions & 3 deletions lib/datacaster/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ module Config

attr_accessor :i18n_t
attr_accessor :i18n_exists
attr_accessor :i18n_module

def add_predefined_caster(name, definition)
caster =
Expand All @@ -20,15 +21,27 @@ def add_predefined_caster(name, definition)
end

def i18n_t
@i18n_t || ->(*args, **kwargs) { I18n.t(*args, **kwargs) }
if @i18n_t.nil? && @i18n_module.nil?
raise RuntimeError, "call Datacaster::Config.i18n_initialize! before defining schemas"
end
@i18n_t || ->(*args, **kwargs) { @i18n_module.t(*args, **kwargs) }
end

def i18n_exists?
@i18n_exists || ->(*args, **kwargs) { I18n.exists?(*args, **kwargs) }
if @i18n_t.nil? && @i18n_module.nil?
raise RuntimeError, "call Datacaster::Config.i18n_initialize! before defining schemas"
end
@i18n_exists || ->(*args, **kwargs) { @i18n_module.exists?(*args, **kwargs) }
end

def i18n_initialize!
I18n.load_path += [__dir__ + '/../../config/locales/en.yml']
@i18n_module ||=
if defined?(::I18n)
I18n
else
SubstituteI18n
end
@i18n_module.load_path += [__dir__ + '/../../config/locales/en.yml']
end
end
end
2 changes: 1 addition & 1 deletion lib/datacaster/definition_dsl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def self.eval(&block)

def method_missing(m, *args)
arg_string = args.empty? ? "" : "(#{args.map(&:inspect).join(', ')})"
raise "Datacaster: unknown definition '#{m}#{arg_string}'"
raise RuntimeError, "Datacaster: unknown definition '#{m}#{arg_string}'", caller
end
end
end
6 changes: 5 additions & 1 deletion lib/datacaster/i18n_values/default_keys.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ def ==(other)
end

def resolve
key = @keys.find(&Config.i18n_exists?) || @keys.first
keys = @keys.select { |x| x[0] != '.' }
if keys.empty?
raise RuntimeError.new("No absolute keys among #{@keys.inspect}. Use #i18n_key or #i18n_default_keys in addition to #i18n_scope.")
end
key = keys.find(&Config.i18n_exists?) || keys.first
Config.i18n_t.(key, **@args)
end

Expand Down
3 changes: 3 additions & 0 deletions lib/datacaster/i18n_values/key.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ def ==(other)
end

def resolve
if @key[0] == '.'
raise RuntimeError.new("Tried to resolve non-absolute key #{@key.inspect}. Use keys which don't start from the dot ('.') in one of related #i18n_key, #i18n_default_keys or #i18n_scope.")
end
Config.i18n_t.(@key, **@args)
end

Expand Down
2 changes: 1 addition & 1 deletion lib/datacaster/i18n_values/scope.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def ==(other)
end

def resolve
Config.i18n_t.(@scope, **@args)
raise RuntimeError.new("Tried to resolve i18n scope #{@scope.inspect}. Use #i18n_key or #i18n_default_keys in addition to #i18n_scope.")
end

def with_args(args)
Expand Down
4 changes: 2 additions & 2 deletions lib/datacaster/predefined.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def transform(&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(catched_exception:, &block)
Expand Down Expand Up @@ -57,7 +57,7 @@ def absent
end

def any
check { |x| x != Datacaster.absent }.i18n_default_keys('.absent', 'datacaster.errors.any')
check { |x| x != Datacaster.absent }.i18n_default_keys('.any', 'datacaster.errors.any')
end

def transform_to_value(value)
Expand Down
4 changes: 2 additions & 2 deletions lib/datacaster/result.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class Result

def initialize(valid, value_or_errors)
@value_or_errors = value_or_errors
unless @value_or_errors.is_a?(Hash) || @value_or_errors.is_a?(Array)
if !valid && !@value_or_errors.is_a?(Hash) && !@value_or_errors.is_a?(Array)
@value_or_errors = Array(@value_or_errors)
end

Expand Down Expand Up @@ -43,7 +43,7 @@ def inspect
end

def to_dry_result
@valid ? Success(@value_or_errors) : Failure(@value_or_errors)
@valid ? Success(@value_or_errors) : Failure(errors)
end

private
Expand Down
45 changes: 0 additions & 45 deletions lib/datacaster/runtime.rb

This file was deleted.

47 changes: 47 additions & 0 deletions lib/datacaster/runtimes/base.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
module Datacaster
module Runtimes
class Base
def self.call(r, proc, *args)
r.instance_exec(*args, &proc)
end

def self.send_to_parent(r, m, *args, &block)
parent = r.instance_variable_get(:@parent)
not_found!(m) if parent.nil?
call(parent, -> { public_send(m, *args, &block) })
end

def self.not_found!(m)
raise NoMethodError.new("Method #{m.inspect} is not available in current runtime context")
end

def initialize(parent = nil)
@parent = parent
end

def method_missing(m, *args, &block)
self.class.send_to_parent(self, m, *args, &block)
end

def respond_to_missing?(m, include_private = false)
!@parent.nil? && @parent.respond_to?(m, include_private)
end

def inspect
"#<#{self.class.name} parent: #{@parent.inspect}>"
end

def to_s
inspect
end

def Success(v)
Datacaster.ValidResult(v)
end

def Failure(v)
Datacaster.ErrorResult(v)
end
end
end
end
2 changes: 1 addition & 1 deletion lib/datacaster/runtimes/i18n.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module Datacaster
module Runtimes
class I18n < Datacaster::Runtime
class I18n < Base
attr_reader :args

def initialize(*)
Expand Down
2 changes: 1 addition & 1 deletion lib/datacaster/runtimes/structure_cleaner.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module Datacaster
module Runtimes
class StructureCleaner < Datacaster::Runtime
class StructureCleaner < Base
attr_reader :checked_schema

def initialize(*)
Expand Down
13 changes: 9 additions & 4 deletions lib/datacaster/runtimes/user_context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

module Datacaster
module Runtimes
class UserContext < Datacaster::Runtime
class UserContext < Base
class ContextStruct
def initialize(parent, user_context)
super(parent)
@context_struct = ContextStruct.new(user_context, self)
def initialize(context, node)
@context = context
@node = node
end

def method_missing(m, *args)
Expand All @@ -26,6 +26,11 @@ def method_missing(m, *args)
end
end

def initialize(parent, user_context)
super(parent)
@context_struct = ContextStruct.new(user_context, self)
end

def context
@context_struct
end
Expand Down
48 changes: 48 additions & 0 deletions lib/datacaster/substitute_i18n.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
require 'yaml'

module Datacaster
module SubstituteI18n
@load_path = []

def self.exists?(key)
!fetch(key).nil?
end

def self.fetch(key)
keys = [locale] + key.split('.')

@translations.each do |hash|
result = hash.dig(*keys)
return result unless result.nil?
end
nil
end

def self.load_path
@load_path
end

def self.load_path=(array)
@load_path = array
@translations = array.map { |x| YAML.load_file(x) }
end

def self.locale
'en'
end

def self.locale=(*)
raise NotImplementedError.new("Setting locale is not supported, use ruby-i18n instead of datacaster's built-in")
end

def self.t(key, **args)
string = fetch(key)
return "Translation missing #{key}" unless string

args.each do |from, to|
string = string.gsub("%{#{from}}", to.to_s)
end
string
end
end
end
7 changes: 3 additions & 4 deletions lib/datacaster/transformer.rb
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
module Datacaster
class Transformer < Base
def initialize(name, &block)
def initialize(&block)
raise "Expected block" unless block_given?

@name = name
@transform = block
end

def cast(object, runtime:)
Datacaster.ValidResult(Runtime.(runtime, @transform, object))
Datacaster.ValidResult(Runtimes::Base.(runtime, @transform, object))
end

def inspect
"#<Datacaster::#{@name}Transformer>"
"#<Datacaster::Transformer>"
end
end
end
10 changes: 4 additions & 6 deletions lib/datacaster/trier.rb
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
module Datacaster
class Trier < Base
def initialize(name, error, catched_exception, &block)
def initialize(catched_exception, &block)
raise "Expected block" unless block_given?

@name = name
@error = error
@catched_exception = Array(catched_exception)
@transform = block
end

def cast(object, runtime:)
begin
Datacaster.ValidResult(Runtime.(runtime, @transform, object))
Datacaster.ValidResult(Runtimes::Base.(runtime, @transform, object))
rescue *@catched_exception
Datacaster.ErrorResult([@error])
Datacaster.ErrorResult(I18nValues::DefaultKeys.new(['.try', 'datacaster.errors.try'], value: object))
end
end

def inspect
"#<Datacaster::#{@name}Trier>"
"#<Datacaster::Trier>"
end
end
end
Loading

0 comments on commit 4c259a3

Please sign in to comment.