plumb 0.0.2 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +636 -129
- data/examples/concurrent_downloads.rb +3 -3
- data/examples/env_config.rb +122 -0
- data/examples/event_registry.rb +120 -0
- data/examples/weekdays.rb +1 -1
- data/lib/plumb/and.rb +4 -3
- data/lib/plumb/any_class.rb +4 -4
- data/lib/plumb/array_class.rb +8 -5
- data/lib/plumb/attributes.rb +262 -0
- data/lib/plumb/build.rb +4 -3
- data/lib/plumb/{steppable.rb → composable.rb} +85 -67
- data/lib/plumb/decorator.rb +57 -0
- data/lib/plumb/deferred.rb +1 -1
- data/lib/plumb/hash_class.rb +20 -11
- data/lib/plumb/hash_map.rb +8 -6
- data/lib/plumb/interface_class.rb +6 -2
- data/lib/plumb/json_schema_visitor.rb +97 -36
- data/lib/plumb/match_class.rb +7 -7
- data/lib/plumb/metadata.rb +5 -1
- data/lib/plumb/metadata_visitor.rb +18 -38
- data/lib/plumb/not.rb +4 -3
- data/lib/plumb/or.rb +10 -4
- data/lib/plumb/pipeline.rb +6 -5
- data/lib/plumb/policies.rb +81 -0
- data/lib/plumb/policy.rb +38 -0
- data/lib/plumb/schema.rb +13 -12
- data/lib/plumb/static_class.rb +4 -3
- data/lib/plumb/step.rb +4 -3
- data/lib/plumb/stream_class.rb +8 -7
- data/lib/plumb/tagged_hash.rb +10 -10
- data/lib/plumb/transform.rb +4 -3
- data/lib/plumb/tuple_class.rb +8 -8
- data/lib/plumb/type_registry.rb +5 -2
- data/lib/plumb/types.rb +119 -23
- data/lib/plumb/value_class.rb +4 -3
- data/lib/plumb/version.rb +1 -1
- data/lib/plumb/visitor_handlers.rb +12 -1
- data/lib/plumb.rb +59 -2
- metadata +12 -7
- data/lib/plumb/rules.rb +0 -102
data/lib/plumb/rules.rb
DELETED
@@ -1,102 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'plumb/steppable'
|
4
|
-
|
5
|
-
module Plumb
|
6
|
-
class Rules
|
7
|
-
UnsupportedRuleError = Class.new(StandardError)
|
8
|
-
UndefinedRuleError = Class.new(KeyError)
|
9
|
-
|
10
|
-
class Registry
|
11
|
-
RuleDef = Data.define(:name, :error_tpl, :callable, :expects) do
|
12
|
-
def supports?(type)
|
13
|
-
types = [type].flatten # may be an array of types for OR logic
|
14
|
-
case expects
|
15
|
-
when Symbol
|
16
|
-
types.all? { |type| type && type.public_instance_methods.include?(expects) }
|
17
|
-
when Class then types.all? { |type| type <= expects }
|
18
|
-
when Object then true
|
19
|
-
else raise "Unexpected expects: #{expects}"
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
Rule = Data.define(:rule_def, :arg_value, :error_str) do
|
25
|
-
def self.build(rule_def, arg_value)
|
26
|
-
error_str = format(rule_def.error_tpl, value: arg_value)
|
27
|
-
new(rule_def, arg_value, error_str)
|
28
|
-
end
|
29
|
-
|
30
|
-
def node_name = :"rule_#{rule_def.name}"
|
31
|
-
def name = rule_def.name
|
32
|
-
|
33
|
-
def error_for(result)
|
34
|
-
return nil if rule_def.callable.call(result, arg_value)
|
35
|
-
|
36
|
-
error_str
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
def initialize
|
41
|
-
@definitions = Hash.new { |h, k| h[k] = Set.new }
|
42
|
-
end
|
43
|
-
|
44
|
-
def define(name, error_tpl, callable = nil, expects: Object, &block)
|
45
|
-
name = name.to_sym
|
46
|
-
callable ||= block
|
47
|
-
@definitions[name] << RuleDef.new(name:, error_tpl:, callable:, expects:)
|
48
|
-
end
|
49
|
-
|
50
|
-
# Ex. size: 3, match: /foo/
|
51
|
-
def resolve(rule_specs, for_type)
|
52
|
-
rule_specs.map do |(name, arg_value)|
|
53
|
-
rule_defs = @definitions.fetch(name.to_sym) { raise UndefinedRuleError, "no rule defined with :#{name}" }
|
54
|
-
rule_def = rule_defs.find { |rd| rd.supports?(for_type) }
|
55
|
-
unless rule_def
|
56
|
-
raise UnsupportedRuleError, "No :#{name} rule for type #{for_type.inspect}" unless for_type.is_a?(Array)
|
57
|
-
|
58
|
-
raise UnsupportedRuleError,
|
59
|
-
"Can't apply :#{name} rule for types #{for_type}. All types must support the same rule implementation"
|
60
|
-
|
61
|
-
end
|
62
|
-
|
63
|
-
Rule.build(rule_def, arg_value)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
include Steppable
|
69
|
-
|
70
|
-
def self.registry
|
71
|
-
@registry ||= Registry.new
|
72
|
-
end
|
73
|
-
|
74
|
-
def self.define(...)
|
75
|
-
registry.define(...)
|
76
|
-
end
|
77
|
-
|
78
|
-
# Ex. new(size: 3, match: /foo/)
|
79
|
-
attr_reader :rules
|
80
|
-
|
81
|
-
def initialize(rule_specs, for_type)
|
82
|
-
@rules = self.class.registry.resolve(rule_specs, for_type).freeze
|
83
|
-
freeze
|
84
|
-
end
|
85
|
-
|
86
|
-
def call(result)
|
87
|
-
errors = []
|
88
|
-
err = nil
|
89
|
-
@rules.each do |rule|
|
90
|
-
err = rule.error_for(result)
|
91
|
-
errors << err if err
|
92
|
-
end
|
93
|
-
return result unless errors.any?
|
94
|
-
|
95
|
-
result.invalid(errors: errors.join(', '))
|
96
|
-
end
|
97
|
-
|
98
|
-
private def _inspect
|
99
|
-
+'Rules(' << @rules.map { |r| [r.name, r.arg_value].join(': ') }.join(', ') << +')'
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|