dry-validation 1.5.0 → 1.5.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5c4b57593ac3fd38a26ef3eb26a31b34503bfa75a6fc118358745aa9fb772be1
4
- data.tar.gz: 534dc4c9e0a8e83faec7077a78e4b3fd7e7fa5b55b6aa277479999332920bcb5
3
+ metadata.gz: ab7416252f8c05238652ca9116ec461448e2024c8d68f7c588e3ef401f7a2ed6
4
+ data.tar.gz: 4137cfee57067480713402f0dd571cb06fde1ef6cafa6feb717596939cbfac1d
5
5
  SHA512:
6
- metadata.gz: 8268526e70a23bd00ff7825accd0b7f4ca682342a2fefab22051e756e574a8b2834d527e1c1e2cce0a7084308eb9d721dafce92b1500c793588ba9d219499e82
7
- data.tar.gz: d1ca0f28f775093521f74330dc4a09142a99c83c693aefcab1571f32343692a72c5f3669bd51baf10865fc9de93074ab3893ddfbb6412edf540bf3f2ac37b47c
6
+ metadata.gz: 01cae726d99151eed0bb1ef1514e8db05f9d10c8d341ffdb8ef7329de9456b63511f5eb390b25113c4da06241dfb1070ca1110ae24a5e050b6c6d5e03e2100a5
7
+ data.tar.gz: 849817760314b9a9e4cc120bc618fc42a302cc08150dcc23eb20c726b1a9b79481b19ca0013674f544608600d7d573d5cf1d1436e826bbcf7d25cf9bd3bad3e6
@@ -1,4 +1,69 @@
1
- ## unreleased
1
+ ## 1.5.5
2
+
3
+ 2020-09-03
4
+
5
+ ### Fixed
6
+
7
+ - Dependency on dry-schema was bumped to >= 1.5.2 (see #666 for more info) (@artofhuman)
8
+
9
+
10
+ [Compare v1.5.4...master](https://github.com/dry-rb/dry-validation/compare/v1.5.4...master)
11
+
12
+ ## 1.5.4 2020-08-21
13
+
14
+
15
+ ### Added
16
+
17
+ - You can now pass any key or a path to the rule's `key?` helper (see #664 for more info) (@alassek)
18
+
19
+ ### Fixed
20
+
21
+ - Full messages work correctly with rule failures now (issue #661 fixed via #662) (@stind)
22
+ - Providing a custom message template for array errors works correctly (issue #663 fixed via #665) (@tadeusz-niemiec)
23
+
24
+
25
+ [Compare v1.5.3...v1.5.4](https://github.com/dry-rb/dry-validation/compare/v1.5.3...v1.5.4)
26
+
27
+ ## 1.5.3 2020-07-27
28
+
29
+
30
+ ### Added
31
+
32
+ - You can now access current value's index via `rule(:foo).each do |index:|` (issue #606 done via #657) (@mrbongiolo)
33
+
34
+ ### Fixed
35
+
36
+ - Using `.each(:foo)` works as expected when there are errors related to other keys (issue #659 fixed via #660) (@solnic)
37
+
38
+ ### Changed
39
+
40
+ - `Result#error?` is now a public API and it takes into consideration both schema and rule errors (issue #655 fixed via #656) (@PragTob)
41
+
42
+ [Compare v1.5.2...v1.5.3](https://github.com/dry-rb/dry-validation/compare/v1.5.2...v1.5.3)
43
+
44
+ ## 1.5.2 2020-07-14
45
+
46
+
47
+ ### Fixed
48
+
49
+ - `key?` predicate in rules no longer crashes when the rule path points to a non-existent array value (issue #653 fixed via #654) (@solnic)
50
+
51
+
52
+ [Compare v1.5.1...v1.5.2](https://github.com/dry-rb/dry-validation/compare/v1.5.1...v1.5.2)
53
+
54
+ ## 1.5.1 2020-06-18
55
+
56
+
57
+ ### Fixed
58
+
59
+ - dry-monads no longer required for the `:hints` extension (@schokomarie)
60
+ - Using `full: true` option works as expected with custom rule messages (issue #618 fixed via #651) (@sirfilip)
61
+ - Using `locale: ...` option works as expected with hints (issue #589 fixed via 652) (@sirfilip)
62
+
63
+
64
+ [Compare v1.5.0...v1.5.1](https://github.com/dry-rb/dry-validation/compare/v1.5.0...v1.5.1)
65
+
66
+ ## 1.5.0 2020-03-11
2
67
 
3
68
 
4
69
  ### Added
@@ -11,7 +76,7 @@
11
76
  - dry-schema dependency was bumped to `~> 1.5` (@solnic)
12
77
  - [internal] `KeyMap` patches have been removed since dry-schema now provides required functionality (@solnic)
13
78
 
14
- [Compare v1.4.2...master](https://github.com/dry-rb/dry-validation/compare/v1.4.2...master)
79
+ [Compare v1.4.2...v1.5.0](https://github.com/dry-rb/dry-validation/compare/v1.4.2...v1.5.0)
15
80
 
16
81
  ## 1.4.2 2020-01-18
17
82
 
@@ -123,14 +123,14 @@ module Dry
123
123
  return path.expand.any? { |nested_path| error?(result, nested_path) }
124
124
  end
125
125
 
126
- return true if result.error?(path)
126
+ return true if result.schema_error?(path)
127
127
 
128
128
  path
129
129
  .to_a[0..-2]
130
130
  .any? { |key|
131
131
  curr_path = Schema::Path[path.keys[0..path.keys.index(key)]]
132
132
 
133
- return false unless result.error?(curr_path)
133
+ return false unless result.schema_error?(curr_path)
134
134
 
135
135
  result.errors.any? { |err|
136
136
  (other = Schema::Path[err.path]).same_root?(curr_path) && other == curr_path
@@ -146,7 +146,7 @@ module Dry
146
146
  #
147
147
  # @return [Object]
148
148
  #
149
- # @public
149
+ # @api public
150
150
  def value
151
151
  values[key_name]
152
152
  end
@@ -155,27 +155,34 @@ module Dry
155
155
  #
156
156
  # This is useful when dealing with rules for optional keys
157
157
  #
158
- # @example
158
+ # @example use the default key name
159
159
  # rule(:age) do
160
160
  # key.failure(:invalid) if key? && value < 18
161
161
  # end
162
162
  #
163
+ # @example specify the key name
164
+ # rule(:start_date, :end_date) do
165
+ # if key?(:start_date) && !key?(:end_date)
166
+ # key(:end_date).failure("must provide an end_date with start_date")
167
+ # end
168
+ # end
169
+ #
163
170
  # @return [Boolean]
164
171
  #
165
172
  # @api public
166
- def key?
167
- values.key?(key_name)
173
+ def key?(name = key_name)
174
+ values.key?(name)
168
175
  end
169
176
 
170
177
  # Check if there are any errors on the schema under the provided path
171
178
  #
172
- # @param [Symbol, String, Array] A Path-compatible spec
179
+ # @param path [Symbol, String, Array] A Path-compatible spec
173
180
  #
174
181
  # @return [Boolean]
175
182
  #
176
183
  # @api public
177
184
  def schema_error?(path)
178
- result.error?(path)
185
+ result.schema_error?(path)
179
186
  end
180
187
 
181
188
  # Check if there are any errors on the current rule
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "dry/monads/result"
4
-
5
3
  module Dry
6
4
  module Validation
7
5
  # Hints extension
@@ -46,7 +44,7 @@ module Dry
46
44
  #
47
45
  # @api public
48
46
  def messages(new_options = EMPTY_HASH)
49
- errors.with(hints.to_a, options.merge(**new_options))
47
+ errors.with(hints(new_options).to_a, options.merge(**new_options))
50
48
  end
51
49
 
52
50
  # Return hint messages
@@ -25,7 +25,7 @@ module Dry
25
25
  # end
26
26
  #
27
27
  # @param [Symbol] name The name of the macro
28
- # @param [Array] *args Optional default arguments for the macro
28
+ # @param [Array] args Optional default positional arguments for the macro
29
29
  #
30
30
  # @return [self]
31
31
  #
@@ -85,7 +85,7 @@ module Dry
85
85
  # @api private
86
86
  def freeze
87
87
  source_messages.select { |err| err.respond_to?(:evaluate) }.each do |err|
88
- idx = source_messages.index(err)
88
+ idx = messages.index(err) || source_messages.index(err)
89
89
  msg = err.evaluate(locale: locale, full: options[:full])
90
90
  messages[idx] = msg
91
91
  end
@@ -1,10 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "dry/validation/message"
4
+ require "dry/schema/message_compiler"
4
5
 
5
6
  module Dry
6
7
  module Validation
7
8
  module Messages
9
+ FULL_MESSAGE_WHITESPACE = Dry::Schema::MessageCompiler::FULL_MESSAGE_WHITESPACE
10
+
8
11
  # Resolve translated messages from failure arguments
9
12
  #
10
13
  # @api public
@@ -33,7 +36,7 @@ module Dry
33
36
  when Symbol
34
37
  Message[->(**opts) { message(message, path: path, tokens: tokens, **opts) }, path, meta]
35
38
  when String
36
- Message[message, path, meta]
39
+ Message[->(**opts) { [message_text(message, path: path, **opts), meta] }, path, meta]
37
40
  when Hash
38
41
  meta = message.dup
39
42
  text = meta.delete(:text) { |key|
@@ -69,6 +72,11 @@ module Dry
69
72
  template, meta = messages[rule, msg_opts.merge(path: keys.last)] unless template
70
73
  end
71
74
 
75
+ if !template && keys.size > 1
76
+ non_index_keys = keys.reject { |k| k.is_a?(Integer) }
77
+ template, meta = messages[rule, msg_opts.merge(path: non_index_keys.join(DOT))]
78
+ end
79
+
72
80
  unless template
73
81
  raise MissingMessageError, <<~STR
74
82
  Message template for #{rule.inspect} under #{keys.join(DOT).inspect} was not found
@@ -78,12 +86,29 @@ module Dry
78
86
  parsed_tokens = parse_tokens(tokens)
79
87
  text = template.(template.data(parsed_tokens))
80
88
 
81
- [full ? "#{messages.rule(keys.last, msg_opts)} #{text}" : text, meta]
89
+ [message_text(text, path: path, locale: locale, full: full), meta]
82
90
  end
83
91
  # rubocop:enable Metrics/AbcSize
84
92
 
85
93
  private
86
94
 
95
+ def message_text(text, path:, locale: nil, full: false)
96
+ return text unless full
97
+
98
+ key = key_text(path: path, locale: locale)
99
+
100
+ [key, text].compact.join(FULL_MESSAGE_WHITESPACE[locale])
101
+ end
102
+
103
+ def key_text(path:, locale: nil)
104
+ locale ||= messages.default_locale
105
+
106
+ keys = path.to_a.compact
107
+ msg_opts = {path: keys, locale: locale}
108
+
109
+ messages.rule(keys.last, msg_opts) || keys.last
110
+ end
111
+
87
112
  def parse_tokens(tokens)
88
113
  Hash[
89
114
  tokens.map do |key, token|
@@ -101,8 +101,15 @@ module Dry
101
101
 
102
102
  # Check if values include an error for the provided key
103
103
  #
104
- # @api private
104
+ # @api public
105
105
  def error?(key)
106
+ errors.any? { |msg| Schema::Path[msg.path].include?(Schema::Path[key]) }
107
+ end
108
+
109
+ # Check if the base schema (without rules) includes an error for the provided key
110
+ #
111
+ # @api private
112
+ def schema_error?(key)
106
113
  schema_result.error?(key)
107
114
  end
108
115
 
@@ -116,7 +123,7 @@ module Dry
116
123
  key_path = Schema::Path[key]
117
124
  err_path = Schema::Path[error.path]
118
125
 
119
- return false unless key_path.same_root?(err_path)
126
+ next unless key_path.same_root?(err_path)
120
127
 
121
128
  key_path == err_path
122
129
  }
@@ -65,8 +65,8 @@ module Dry
65
65
  # for a given array item.
66
66
  #
67
67
  # @example
68
- # rule(:nums).each do
69
- # key.failure("must be greater than 0") if value < 0
68
+ # rule(:nums).each do |index:|
69
+ # key([:number, index]).failure("must be greater than 0") if value < 0
70
70
  # end
71
71
  # rule(:nums).each(min: 3)
72
72
  # rule(address: :city) do
@@ -86,9 +86,9 @@ module Dry
86
86
  values[root].each_with_index do |_, idx|
87
87
  path = [*Schema::Path[root].to_a, idx]
88
88
 
89
- next if result.error?(path)
89
+ next if result.schema_error?(path)
90
90
 
91
- evaluator = with(macros: macros, keys: [path], &block)
91
+ evaluator = with(macros: macros, keys: [path], index: idx, &block)
92
92
 
93
93
  failures.concat(evaluator.failures)
94
94
  end
@@ -35,7 +35,10 @@ module Dry
35
35
  # key.failure('must be > 18') if values[:age] <= 18
36
36
  # end
37
37
  #
38
- # @param [Symbol] key
38
+ # @param args [Symbol, String, Hash, Array<Symbol>] If given as a single
39
+ # Symbol, String, Array or Hash, build a key array using
40
+ # {Dry::Schema::Path} digging for data. If given as positional
41
+ # arguments, use these with Hash#dig on the data directly.
39
42
  #
40
43
  # @return [Object]
41
44
  #
@@ -65,6 +68,8 @@ module Dry
65
68
  if e.is_a?(Array)
66
69
  result = e.all? { |k| key?(k, a) }
67
70
  return result
71
+ elsif e.is_a?(Symbol) && a.is_a?(Array)
72
+ return false
68
73
  else
69
74
  return false unless a.is_a?(Array) ? (e >= 0 && e < a.size) : a.key?(e)
70
75
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Dry
4
4
  module Validation
5
- VERSION = "1.5.0"
5
+ VERSION = "1.5.5"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dry-validation
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.0
4
+ version: 1.5.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotr Solnica
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-03-11 00:00:00.000000000 Z
11
+ date: 2020-09-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby