dry-mutations 0.8.98 → 0.8.99
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/.rubocop_todo.yml +0 -6
- data/lib/dry/mutations/extensions/command.rb +1 -5
- data/lib/dry/mutations/extensions/dummy.rb +12 -6
- data/lib/dry/mutations/transactions/step_adapters/tranquilo.rb +1 -0
- data/lib/dry/mutations/utils.rb +3 -139
- data/lib/dry/mutations/utils/dry-mutations.rb +74 -0
- data/lib/dry/mutations/utils/generic.rb +60 -0
- data/lib/dry/mutations/utils/procs.rb +27 -0
- data/lib/dry/mutations/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: adf3c66151551d8178bec6e8cb4be0cebc44c510
|
|
4
|
+
data.tar.gz: 511479d97e75272438c8ae12c2800b8fd7b7e4d3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 87e8f198e537c75f70fb563efec3fea2611628283851ddf41b3d1e2f27ea8c6549d2a49d23a227e1f1575995ad5286ea3a6f1e4c758b189a70cbe575236b6b0c
|
|
7
|
+
data.tar.gz: be2bde7e5fd9f2a237bc5669b57ab3f5ef435bfdbdc591be543e9da0d7e5fd47bf1792ba1a05e38e5ac8fb6622ffe2bb12fa2698200885df2a7e11a5ddbfc1f3
|
data/.rubocop.yml
CHANGED
data/.rubocop_todo.yml
CHANGED
|
@@ -35,9 +35,3 @@ Style/FirstParameterIndentation:
|
|
|
35
35
|
# SupportedStyles: single_quotes, double_quotes
|
|
36
36
|
Style/StringLiterals:
|
|
37
37
|
Enabled: false
|
|
38
|
-
|
|
39
|
-
# Offense count: 2
|
|
40
|
-
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
|
41
|
-
# SupportedStyles: snake_case, camelCase
|
|
42
|
-
Style/VariableName:
|
|
43
|
-
Enabled: false
|
|
@@ -35,11 +35,7 @@ module Dry
|
|
|
35
35
|
attr_reader :validation
|
|
36
36
|
|
|
37
37
|
def initialize(*args)
|
|
38
|
-
@raw_inputs =
|
|
39
|
-
arg = arg.value if arg.is_a?(Right)
|
|
40
|
-
fail ArgumentError.new("All arguments must be hashes. Given: #{args.inspect}.") unless arg.is_a?(Hash)
|
|
41
|
-
h.merge!(arg)
|
|
42
|
-
end
|
|
38
|
+
@raw_inputs = Utils.RawInputs(*args)
|
|
43
39
|
|
|
44
40
|
@validation_result = schema.(@raw_inputs)
|
|
45
41
|
|
|
@@ -17,17 +17,23 @@ module Dry
|
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
+
module Hole # :nodoc:
|
|
21
|
+
def initialize(*args)
|
|
22
|
+
@raw_inputs = Utils.RawInputs(*args)
|
|
23
|
+
# @validation_result = schema.(@raw_inputs)
|
|
24
|
+
@inputs = Utils.Hash @raw_inputs
|
|
25
|
+
@errors = nil
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
20
29
|
# rubocop:disable Style/ConstantName
|
|
21
30
|
Dummy = ENV['USE_SIEVE_AS_DUMMY'] ? Sieve : Pipe
|
|
22
31
|
# rubocop:enable Style/ConstantName
|
|
23
32
|
|
|
24
33
|
module Wrapper # :nodoc:
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
{ Utils.Snake(self.class, short: true, symbolize: true) => super }
|
|
29
|
-
end
|
|
30
|
-
end)
|
|
34
|
+
def execute
|
|
35
|
+
{ Utils.Snake(self.class, short: true, symbolize: true) => super }
|
|
36
|
+
end
|
|
31
37
|
end
|
|
32
38
|
end
|
|
33
39
|
end
|
|
@@ -6,6 +6,7 @@ module Dry
|
|
|
6
6
|
# which should return the step’s result wrapped in an `Either` object.
|
|
7
7
|
class Tranquilo < StepAdapters::Move # :nodoc:
|
|
8
8
|
def call(step, *args, input)
|
|
9
|
+
# TODO: FIXME: PENDING: when block passing is merged into dry-validation
|
|
9
10
|
step.operation.(input, *args)
|
|
10
11
|
end
|
|
11
12
|
end
|
data/lib/dry/mutations/utils.rb
CHANGED
|
@@ -1,139 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
FALSEY = /\A#{Regexp.union(%w(0 skip false falsey no n)).source}\z/i
|
|
5
|
-
TRUTHY = /\A#{Regexp.union(%w(1 use true truthy yes y)).source}\z/i
|
|
6
|
-
|
|
7
|
-
def self.Falsey? input, explicit: true
|
|
8
|
-
explicit ? input.to_s =~ FALSEY : input.to_s !~ TRUTHY
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def self.Truthy? input, explicit: true
|
|
12
|
-
explicit ? input.to_s =~ TRUTHY : input.to_s !~ FALSEY
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def self.Snake(whatever, short: false, symbolize: false)
|
|
16
|
-
result = whatever.to_s.split('::').map do |e|
|
|
17
|
-
e.gsub(/(?<=[^\W_])(?=[A-Z])/, '_').downcase
|
|
18
|
-
end
|
|
19
|
-
result = short ? result.last : result.join('__')
|
|
20
|
-
symbolize ? result.to_sym : result
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def self.SnakeSafe(whatever, existing = [], update_existing: true, short: false, symbolize: false)
|
|
24
|
-
result = Snake(whatever, short: short)
|
|
25
|
-
str = loop do
|
|
26
|
-
break result unless existing.include? result
|
|
27
|
-
suffix = result[/(?<=_)\d+(?=\z)/]
|
|
28
|
-
suffix.nil? ? result << '_1' : result[-suffix.length..-1] = (suffix.to_i + 1).to_s
|
|
29
|
-
end.tap { |r| existing << r if update_existing }
|
|
30
|
-
symbolize ? str.to_sym : str
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def self.Camel(whatever)
|
|
34
|
-
whatever.to_s.split('__').map do |s|
|
|
35
|
-
s.gsub(/(?:\A|_)(?<letter>\w)/) { $~[:letter].upcase }
|
|
36
|
-
end.join('::')
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
def self.Constant(whatever)
|
|
40
|
-
::Kernel.const_get(Camel(whatever))
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def self.Λ input, **params
|
|
44
|
-
case
|
|
45
|
-
when params[:method] then input.method(params.delete[:method].to_sym).to_proc
|
|
46
|
-
when input.respond_to?(:to_proc) then input.to_proc
|
|
47
|
-
when input.respond_to?(:call) then input.method(:call).to_proc
|
|
48
|
-
else fail ArgumentError, "The executor given can not be executed (forgot to specify :method param?)"
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
# Lazy detector for Hashie::Mash
|
|
53
|
-
# TODO: Make it possible to choose friendly hash implementation
|
|
54
|
-
USE_HASHIE_MASH = Falsey?(ENV['PLAIN_HASHES'], explicit: false) && begin
|
|
55
|
-
require 'hashie/mash'
|
|
56
|
-
true
|
|
57
|
-
rescue LoadError => e
|
|
58
|
-
$stderr.puts [
|
|
59
|
-
'[DRY] Could not find Hashie::Mash.',
|
|
60
|
-
'You probably want to install it / add it to your Gemfile.',
|
|
61
|
-
"Error: [#{e.message}]."
|
|
62
|
-
].join($/)
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
# Converts a hash to a best available hash implementation
|
|
66
|
-
# with stringified keys, since `Mutations` expect hash
|
|
67
|
-
# keys to be strings.
|
|
68
|
-
def self.Hash hash = {}
|
|
69
|
-
case
|
|
70
|
-
when USE_HASHIE_MASH
|
|
71
|
-
Kernel.const_get('::Hashie::Mash').new(hash)
|
|
72
|
-
when hash.respond_to?(:with_indifferent_access)
|
|
73
|
-
hash.with_indifferent_access
|
|
74
|
-
else
|
|
75
|
-
hash.map { |k, v| [k.to_s, v] }.to_h
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
ITSELF = ->(h, k) { h[k] = k }
|
|
80
|
-
DRY_TO_MUTATIONS = {
|
|
81
|
-
min_size?: :min_length,
|
|
82
|
-
max_size?: :max_length,
|
|
83
|
-
format?: :matches,
|
|
84
|
-
inclusion?: :in, # deprecated in Dry
|
|
85
|
-
included_in?: :in,
|
|
86
|
-
gteq?: :min,
|
|
87
|
-
lteq?: :max
|
|
88
|
-
}.freeze
|
|
89
|
-
MUTATIONS_TO_DRY = DRY_TO_MUTATIONS.invert.merge(default: :default?).freeze
|
|
90
|
-
|
|
91
|
-
# Fuzzy converts params between different implementaions
|
|
92
|
-
def self.Guards *keys, **params
|
|
93
|
-
return {} if params.empty? || params[:empty] # Mutations `empty?` guard takes precedence on all others
|
|
94
|
-
|
|
95
|
-
keys = params.keys if keys.empty?
|
|
96
|
-
keys.flatten! # allow array to be passed as the only parameter
|
|
97
|
-
|
|
98
|
-
map = [DRY_TO_MUTATIONS, MUTATIONS_TO_DRY].detect do |h|
|
|
99
|
-
(h.keys & keys).any?
|
|
100
|
-
end || Hash.new(&ITSELF)
|
|
101
|
-
|
|
102
|
-
map.values_at(*keys).zip(keys.map(¶ms.method(:[])))
|
|
103
|
-
.to_h
|
|
104
|
-
.tap { |h| h.delete(nil) }
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
def self.Type type, **params
|
|
108
|
-
case type.to_s
|
|
109
|
-
when 'string'
|
|
110
|
-
if Falsey?(params[:strip])
|
|
111
|
-
:str?
|
|
112
|
-
else
|
|
113
|
-
# TODO: this silently coerces everything to be a string
|
|
114
|
-
# when `param[:strip]` is specified. This is likely OK, though.
|
|
115
|
-
::Dry::Types::Constructor.new(
|
|
116
|
-
::Dry::Types['strict.string'], fn: ->(v) { v.to_s.strip }
|
|
117
|
-
)
|
|
118
|
-
end
|
|
119
|
-
when 'date'
|
|
120
|
-
::Dry::Types::Constructor.new(
|
|
121
|
-
::Dry::Types['strict.date'], fn: ->(v) { v.is_a?(Date) ? v : (Date.parse(v.to_s) rescue v) }
|
|
122
|
-
)
|
|
123
|
-
when 'integer'
|
|
124
|
-
:int?
|
|
125
|
-
# FIXME: Why ints are not coercible?!
|
|
126
|
-
#::Dry::Types::Constructor.new(
|
|
127
|
-
# ::Dry::Types['coercible.int'], fn: ->(v) { v.is_a?(Integer) ? v : (v.to_i rescue v) }
|
|
128
|
-
#)
|
|
129
|
-
when 'boolean' then :bool?
|
|
130
|
-
else :"#{type}?"
|
|
131
|
-
end
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
def self.smart_send receiver, *args, **params
|
|
135
|
-
params.empty? ? receiver.__send__(*args) : receiver.__send__(*args, **params)
|
|
136
|
-
end
|
|
137
|
-
end
|
|
138
|
-
end
|
|
139
|
-
end
|
|
1
|
+
require 'dry/mutations/utils/generic'
|
|
2
|
+
require 'dry/mutations/utils/procs'
|
|
3
|
+
require 'dry/mutations/utils/dry-mutations'
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
module Dry
|
|
2
|
+
module Mutations
|
|
3
|
+
module Utils # :nodoc:
|
|
4
|
+
DRY_TO_MUTATIONS = {
|
|
5
|
+
min_size?: :min_length,
|
|
6
|
+
max_size?: :max_length,
|
|
7
|
+
format?: :matches,
|
|
8
|
+
inclusion?: :in, # deprecated in Dry
|
|
9
|
+
included_in?: :in,
|
|
10
|
+
gteq?: :min,
|
|
11
|
+
lteq?: :max
|
|
12
|
+
}.freeze
|
|
13
|
+
MUTATIONS_TO_DRY = DRY_TO_MUTATIONS.invert.merge(default: :default?).freeze
|
|
14
|
+
|
|
15
|
+
def self.RawInputs *args
|
|
16
|
+
args.inject(Utils.Hash({})) do |h, arg|
|
|
17
|
+
h.merge! case arg
|
|
18
|
+
when Hash then arg
|
|
19
|
+
when ::Dry::Monads::Either::Right then arg.value
|
|
20
|
+
when ::Dry::Monads::Either::Left then fail ArgumentError.new("Can’t accept Left value: #{args.inspect}.")
|
|
21
|
+
else fail ArgumentError.new("All arguments must be hashes. Given: #{args.inspect}.") unless arg.is_a?(Hash)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Fuzzy converts params between different implementaions
|
|
27
|
+
def self.Guards *keys, **params
|
|
28
|
+
return {} if params.empty? || params[:empty] # Mutations `empty?` guard takes precedence on all others
|
|
29
|
+
|
|
30
|
+
keys = params.keys if keys.empty?
|
|
31
|
+
keys.flatten! # allow array to be passed as the only parameter
|
|
32
|
+
|
|
33
|
+
map = [DRY_TO_MUTATIONS, MUTATIONS_TO_DRY].detect do |h|
|
|
34
|
+
(h.keys & keys).any?
|
|
35
|
+
end || Hash.new(&ITSELF)
|
|
36
|
+
|
|
37
|
+
map.values_at(*keys).zip(keys.map(¶ms.method(:[])))
|
|
38
|
+
.to_h
|
|
39
|
+
.tap { |h| h.delete(nil) }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def self.Type type, **params
|
|
43
|
+
case type.to_s
|
|
44
|
+
when 'string'
|
|
45
|
+
if Falsey?(params[:strip])
|
|
46
|
+
:str?
|
|
47
|
+
else
|
|
48
|
+
# TODO: this silently coerces everything to be a string
|
|
49
|
+
# when `param[:strip]` is specified. This is likely OK, though.
|
|
50
|
+
::Dry::Types::Constructor.new(
|
|
51
|
+
::Dry::Types['strict.string'], fn: ->(v) { v.to_s.strip }
|
|
52
|
+
)
|
|
53
|
+
end
|
|
54
|
+
when 'date'
|
|
55
|
+
::Dry::Types::Constructor.new(
|
|
56
|
+
::Dry::Types['strict.date'], fn: ->(v) { v.is_a?(Date) ? v : (Date.parse(v.to_s) rescue v) }
|
|
57
|
+
)
|
|
58
|
+
when 'integer'
|
|
59
|
+
:int?
|
|
60
|
+
# FIXME: Why ints are not coercible?!
|
|
61
|
+
#::Dry::Types::Constructor.new(
|
|
62
|
+
# ::Dry::Types['coercible.int'], fn: ->(v) { v.is_a?(Integer) ? v : (v.to_i rescue v) }
|
|
63
|
+
# )
|
|
64
|
+
when 'boolean' then :bool?
|
|
65
|
+
else :"#{type}?"
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def self.smart_send receiver, *args, **params
|
|
70
|
+
params.empty? ? receiver.__send__(*args) : receiver.__send__(*args, **params)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
module Dry
|
|
2
|
+
module Mutations
|
|
3
|
+
module Utils # :nodoc:
|
|
4
|
+
FALSEY = /\A#{Regexp.union(%w(0 skip false falsey no n)).source}\z/i
|
|
5
|
+
TRUTHY = /\A#{Regexp.union(%w(1 use true truthy yes y)).source}\z/i
|
|
6
|
+
|
|
7
|
+
def self.Falsey? input, explicit: true
|
|
8
|
+
explicit ? input.to_s =~ FALSEY : input.to_s !~ TRUTHY
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def self.Truthy? input, explicit: true
|
|
12
|
+
explicit ? input.to_s =~ TRUTHY : input.to_s !~ FALSEY
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.Snake(whatever, short: false, symbolize: false)
|
|
16
|
+
result = whatever.to_s.split('::').map do |e|
|
|
17
|
+
e.gsub(/(?<=[^\W_])(?=[A-Z])/, '_').downcase
|
|
18
|
+
end
|
|
19
|
+
result = short ? result.last : result.join('__')
|
|
20
|
+
symbolize ? result.to_sym : result
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def self.SnakeSafe(whatever, existing = [], update_existing: true, short: false, symbolize: false)
|
|
24
|
+
result = Snake(whatever, short: short)
|
|
25
|
+
str = loop do
|
|
26
|
+
break result unless existing.include? result
|
|
27
|
+
suffix = result[/(?<=_)\d+(?=\z)/]
|
|
28
|
+
suffix.nil? ? result << '_1' : result[-suffix.length..-1] = (suffix.to_i + 1).to_s
|
|
29
|
+
end.tap { |r| existing << r if update_existing }
|
|
30
|
+
symbolize ? str.to_sym : str
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def self.Camel(whatever)
|
|
34
|
+
whatever.to_s.split('__').map do |s|
|
|
35
|
+
s.gsub(/(?:\A|_)(?<letter>\w)/) { $~[:letter].upcase }
|
|
36
|
+
end.join('::')
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def self.Constant(whatever)
|
|
40
|
+
::Kernel.const_get(Camel(whatever))
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Converts a hash to a best available hash implementation
|
|
44
|
+
# with stringified keys, since `Mutations` expect hash
|
|
45
|
+
# keys to be strings.
|
|
46
|
+
def self.Hash hash = {}
|
|
47
|
+
case
|
|
48
|
+
when USE_HASHIE_MASH
|
|
49
|
+
Kernel.const_get('::Hashie::Mash').new(hash)
|
|
50
|
+
when hash.respond_to?(:with_indifferent_access)
|
|
51
|
+
hash.with_indifferent_access
|
|
52
|
+
else
|
|
53
|
+
hash.map { |k, v| [k.to_s, v] }.to_h
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
ITSELF = ->(h, k) { h[k] = k }
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module Dry
|
|
2
|
+
module Mutations
|
|
3
|
+
module Utils # :nodoc:
|
|
4
|
+
def self.Λ input, **params
|
|
5
|
+
case
|
|
6
|
+
when params[:method] then input.method(params.delete[:method].to_sym).to_proc
|
|
7
|
+
when input.respond_to?(:to_proc) then input.to_proc
|
|
8
|
+
when input.respond_to?(:call) then input.method(:call).to_proc
|
|
9
|
+
else fail ArgumentError, "The executor given can not be executed (forgot to specify :method param?)"
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Lazy detector for Hashie::Mash
|
|
14
|
+
# TODO: Make it possible to choose friendly hash implementation
|
|
15
|
+
USE_HASHIE_MASH = Falsey?(ENV['PLAIN_HASHES'], explicit: false) && begin
|
|
16
|
+
require 'hashie/mash'
|
|
17
|
+
true
|
|
18
|
+
rescue LoadError => e
|
|
19
|
+
$stderr.puts [
|
|
20
|
+
'[DRY] Could not find Hashie::Mash.',
|
|
21
|
+
'You probably want to install it / add it to your Gemfile.',
|
|
22
|
+
"Error: [#{e.message}]."
|
|
23
|
+
].join($/)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dry-mutations
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.8.
|
|
4
|
+
version: 0.8.99
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Aleksei Matiushkin
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2016-08-
|
|
11
|
+
date: 2016-08-09 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -231,6 +231,9 @@ files:
|
|
|
231
231
|
- lib/dry/mutations/transactions/step_adapters/validate.rb
|
|
232
232
|
- lib/dry/mutations/transactions/wrapper.rb
|
|
233
233
|
- lib/dry/mutations/utils.rb
|
|
234
|
+
- lib/dry/mutations/utils/dry-mutations.rb
|
|
235
|
+
- lib/dry/mutations/utils/generic.rb
|
|
236
|
+
- lib/dry/mutations/utils/procs.rb
|
|
234
237
|
- lib/dry/mutations/version.rb
|
|
235
238
|
homepage: http://github.com/am-kantox/dry-mutations
|
|
236
239
|
licenses:
|