hanami-validations 1.3.7 → 2.0.0.beta1

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.
@@ -16,16 +16,14 @@ Gem::Specification.new do |spec|
16
16
 
17
17
  spec.files = `git ls-files -- lib/* LICENSE.md README.md CHANGELOG.md hanami-validations.gemspec`.split($/)
18
18
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
19
  spec.require_paths = ["lib"]
21
- spec.required_ruby_version = ">= 2.3.0"
20
+ spec.metadata["rubygems_mfa_required"] = "true"
21
+ spec.required_ruby_version = ">= 3.0"
22
22
 
23
- spec.add_dependency "hanami-utils", "~> 1.3"
24
- spec.add_dependency "dry-validation", "~> 0.11", "< 0.12"
25
- spec.add_dependency "dry-logic", "~> 0.4.2", "< 0.5"
23
+ spec.add_dependency "dry-validation", "~> 1.6"
26
24
 
27
25
  spec.add_development_dependency "bundler", ">= 1.6", "< 3"
28
26
  spec.add_development_dependency "rake", "~> 13"
29
27
  spec.add_development_dependency "rspec", "~> 3.9"
30
- spec.add_development_dependency "rubocop", "0.81" # rubocop 0.81+ removed support for Ruby 2.3
28
+ spec.add_development_dependency "rubocop", "~> 1.0"
31
29
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "hanami/validations"
4
-
5
3
  module Hanami
6
4
  module Validations
7
5
  # Validations mixin for forms/HTTP params.
@@ -12,57 +10,65 @@ module Hanami
12
10
  # @since 0.6.0
13
11
  #
14
12
  # @example
15
- # require 'hanami/validations/form'
13
+ # require "hanami/validations/form"
16
14
  #
17
15
  # class Signup
18
16
  # include Hanami::Validations::Form
19
17
  #
20
18
  # validations do
21
- # required(:name).filled(:str?)
22
- # optional(:location).filled(:str?)
19
+ # required(:name).filled(:string)
20
+ # optional(:location).filled(:string)
23
21
  # end
24
22
  # end
25
23
  #
26
- # result = Signup.new('location' => 'Rome').validate
24
+ # result = Signup.new("location" => "Rome").validate
27
25
  # result.success? # => false
28
26
  #
29
- # result = Signup.new('name' => 'Luca').validate
27
+ # result = Signup.new("name" => "Luca").validate
30
28
  # result.success? # => true
31
29
  #
32
30
  # # it works with symbol keys too
33
- # result = Signup.new(location: 'Rome').validate
31
+ # result = Signup.new(location: "Rome").validate
34
32
  # result.success? # => false
35
33
  #
36
- # result = Signup.new(name: 'Luca').validate
34
+ # result = Signup.new(name: "Luca").validate
37
35
  # result.success? # => true
38
36
  #
39
- # result = Signup.new(name: 'Luca', location: 'Rome').validate
37
+ # result = Signup.new(name: "Luca", location: "Rome").validate
40
38
  # result.success? # => true
41
39
  module Form
40
+ # @since 2.0.0
41
+ # @api private
42
+ class BaseValidator < Dry::Validation::Contract
43
+ params do
44
+ optional(:_csrf_token).filled(:string)
45
+ end
46
+ end
47
+
42
48
  # Override Ruby's hook for modules.
43
49
  #
44
- # @param base [Class] the target action
50
+ # @param klass [Class] the target action
45
51
  #
46
52
  # @since 0.6.0
47
53
  # @api private
48
54
  #
49
55
  # @see http://www.ruby-doc.org/core/Module.html#method-i-included
50
- def self.included(base)
51
- base.class_eval do
52
- include Validations
53
- extend ClassMethods
56
+ def self.included(klass)
57
+ super
58
+
59
+ klass.class_eval do
60
+ include ::Hanami::Validations
61
+ extend ClassMethods
54
62
  end
55
63
  end
56
64
 
57
65
  # @since 0.6.0
58
66
  # @api private
59
67
  module ClassMethods
60
- private
61
-
62
- # @since 0.6.0
68
+ # @since 2.0.0
63
69
  # @api private
64
- def _schema_type
65
- :Form
70
+ def validations(&blk)
71
+ @_validator = Class.new(BaseValidator) { params(&blk) }.new
66
72
  end
67
73
  end
68
74
  end
@@ -3,6 +3,6 @@
3
3
  module Hanami
4
4
  module Validations
5
5
  # @since 0.1.0
6
- VERSION = "1.3.7"
6
+ VERSION = "2.0.0.beta1"
7
7
  end
8
8
  end
@@ -1,65 +1,34 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "dry-validation"
4
- require "hanami/utils/class_attribute"
5
- require "hanami/validations/namespace"
6
- require "hanami/validations/predicates"
7
- require "hanami/validations/inline_predicate"
8
- require "set"
3
+ require "dry/validation"
4
+ require "delegate"
9
5
 
10
- Dry::Validation::Messages::Namespaced.configure do |config|
11
- # rubocop:disable Lint/NestedPercentLiteral
12
- #
13
- # This is probably a false positive.
14
- # See: https://github.com/bbatsov/rubocop/issues/5314
15
- config.lookup_paths = config.lookup_paths + %w[
16
- %<root>s.%<rule>s.%<predicate>s
17
- ].freeze
18
- # rubocop:enable Lint/NestedPercentLiteral
19
- end
20
-
21
- # @since 0.1.0
22
6
  module Hanami
23
- # Hanami::Validations is a set of lightweight validations for Ruby objects.
24
- #
25
7
  # @since 0.1.0
26
- #
27
- # @example
28
- # require 'hanami/validations'
29
- #
30
- # class Signup
31
- # include Hanami::Validations
32
- #
33
- # validations do
34
- # # ...
35
- # end
36
- # end
37
8
  module Validations
38
- # @since 0.6.0
39
- # @api private
40
- DEFAULT_MESSAGES_ENGINE = :yaml
9
+ class Error < StandardError; end
41
10
 
42
- # Override Ruby's hook for modules.
43
- #
44
- # @param base [Class] the target action
45
- #
46
- # @since 0.1.0
47
- # @api private
48
- #
49
- # @see http://www.ruby-doc.org/core/Module.html#method-i-included
50
- def self.included(base)
51
- base.class_eval do
52
- extend ClassMethods
11
+ require "hanami/validations/version"
12
+ require "hanami/validator"
53
13
 
54
- include Utils::ClassAttribute
55
- class_attribute :schema
56
- class_attribute :_messages
57
- class_attribute :_messages_path
58
- class_attribute :_namespace
59
- class_attribute :_predicates_module
14
+ def self.included(klass)
15
+ super
16
+ klass.extend(ClassMethods)
17
+ end
18
+
19
+ # @since 2.0.0
20
+ # @api private
21
+ class Result < SimpleDelegator
22
+ # @since 2.0.0
23
+ # @api private
24
+ def output
25
+ __getobj__.to_h
26
+ end
60
27
 
61
- class_attribute :_predicates
62
- self._predicates = Set.new
28
+ # @since 2.0.0
29
+ # @api private
30
+ def messages
31
+ __getobj__.errors.to_h
63
32
  end
64
33
  end
65
34
 
@@ -76,13 +45,13 @@ module Hanami
76
45
  # @see https://guides.hanamirb.org/validations/overview
77
46
  #
78
47
  # @example Basic Example
79
- # require 'hanami/validations'
48
+ # require "hanami/validations"
80
49
  #
81
50
  # class Signup
82
51
  # include Hanami::Validations
83
52
  #
84
53
  # validations do
85
- # required(:name).filled
54
+ # required(:name).filled(:string)
86
55
  # end
87
56
  # end
88
57
  #
@@ -98,260 +67,13 @@ module Hanami
98
67
  # result.messages # => {:name=>["must be filled"]}
99
68
  # result.output # => {:name=>""}
100
69
  def validations(&blk)
101
- schema_predicates = __predicates
102
-
103
- base = _build(predicates: schema_predicates, &_base_rules)
104
- schema = _build(predicates: schema_predicates, rules: base.rules, &blk)
105
- schema.configure(&_schema_config)
106
- schema.configure(&_schema_predicates)
107
- schema.extend(__messages) unless _predicates.empty?
108
-
109
- self.schema = schema.new
110
- end
111
-
112
- # Define an inline predicate
113
- #
114
- # @param name [Symbol] inline predicate name
115
- # @param message [String] optional error message
116
- # @param blk [Proc] predicate implementation
117
- #
118
- # @return nil
119
- #
120
- # @since 0.6.0
121
- #
122
- # @example Without Custom Message
123
- # require 'hanami/validations'
124
- #
125
- # class Signup
126
- # include Hanami::Validations
127
- #
128
- # predicate :foo? do |actual|
129
- # actual == 'foo'
130
- # end
131
- #
132
- # validations do
133
- # required(:name).filled(:foo?)
134
- # end
135
- # end
136
- #
137
- # result = Signup.new(name: nil).call
138
- # result.messages # => { :name => ['is invalid'] }
139
- #
140
- # @example With Custom Message
141
- # require 'hanami/validations'
142
- #
143
- # class Signup
144
- # include Hanami::Validations
145
- #
146
- # predicate :foo?, message: 'must be foo' do |actual|
147
- # actual == 'foo'
148
- # end
149
- #
150
- # validations do
151
- # required(:name).filled(:foo?)
152
- # end
153
- # end
154
- #
155
- # result = Signup.new(name: nil).call
156
- # result.messages # => { :name => ['must be foo'] }
157
- def predicate(name, message: "is invalid", &blk)
158
- _predicates << InlinePredicate.new(name, message, &blk)
159
- end
160
-
161
- # Assign a set of shared predicates wrapped in a module
162
- #
163
- # @param mod [Module] a module with shared predicates
164
- #
165
- # @since 0.6.0
166
- #
167
- # @see Hanami::Validations::Predicates
168
- #
169
- # @example
170
- # require 'hanami/validations'
171
- #
172
- # module MySharedPredicates
173
- # include Hanami::Validations::Predicates
174
- #
175
- # predicate :foo? fo |actual|
176
- # actual == 'foo'
177
- # end
178
- # end
179
- #
180
- # class MyValidator
181
- # include Hanami::Validations
182
- # predicates MySharedPredicates
183
- #
184
- # validations do
185
- # required(:name).filled(:foo?)
186
- # end
187
- # end
188
- def predicates(mod)
189
- self._predicates_module = mod
190
- end
191
-
192
- # Define the type of engine for error messages.
193
- #
194
- # Accepted values are `:yaml` (default), `:i18n`.
195
- #
196
- # @param type [Symbol] the preferred engine
197
- #
198
- # @since 0.6.0
199
- #
200
- # @example
201
- # require 'hanami/validations'
202
- #
203
- # class Signup
204
- # include Hanami::Validations
205
- #
206
- # messages :i18n
207
- # end
208
- def messages(type)
209
- self._messages = type
210
- end
211
-
212
- # Define the path where to find translation file
213
- #
214
- # @param path [String] path to translation file
215
- #
216
- # @since 0.6.0
217
- #
218
- # @example
219
- # require 'hanami/validations'
220
- #
221
- # class Signup
222
- # include Hanami::Validations
223
- #
224
- # messages_path 'config/messages.yml'
225
- # end
226
- def messages_path(path)
227
- self._messages_path = path
228
- end
229
-
230
- # Namespace for error messages.
231
- #
232
- # @param name [String] namespace
233
- #
234
- # @since 0.6.0
235
- #
236
- # @example
237
- # require 'hanami/validations'
238
- #
239
- # module MyApp
240
- # module Validators
241
- # class Signup
242
- # include Hanami::Validations
243
- #
244
- # namespace 'signup'
245
- # end
246
- # end
247
- # end
248
- #
249
- # # Instead of looking for error messages under the `my_app.validator.signup`
250
- # # namespace, it will look just for `signup`.
251
- # #
252
- # # This helps to simplify YAML files where are stored error messages
253
- def namespace(name = nil)
254
- if name.nil?
255
- Namespace.new(_namespace, self)
256
- else
257
- self._namespace = name.to_s
258
- end
259
- end
260
-
261
- private
262
-
263
- # @since 0.6.0
264
- # @api private
265
- def _build(options = {}, &blk)
266
- options = {build: false}.merge(options)
267
- Dry::Validation.__send__(_schema_type, options, &blk)
70
+ @_validator = Dry::Validation::Contract.build { schema(&blk) }
268
71
  end
269
72
 
270
- # @since 0.6.0
73
+ # @since 2.0.0
271
74
  # @api private
272
- def _schema_type
273
- :Schema
274
- end
275
-
276
- # @since 0.6.0
277
- # @api private
278
- def _base_rules
279
- lambda do
280
- end
281
- end
282
-
283
- # @since 0.6.0
284
- # @api private
285
- def _schema_config
286
- lambda do |config|
287
- config.messages = _messages unless _messages.nil?
288
- config.messages_file = _messages_path unless _messages_path.nil?
289
- config.namespace = namespace
290
-
291
- require "dry/validation/messages/i18n" if config.messages == :i18n
292
- end
293
- end
294
-
295
- # @since 0.6.0
296
- # @api private
297
- def _schema_predicates
298
- return if _predicates_module.nil? && _predicates.empty?
299
-
300
- lambda do |config|
301
- config.messages = _predicates_module&.messages || @_messages || DEFAULT_MESSAGES_ENGINE
302
- config.messages_file = _predicates_module.messages_path unless _predicates_module.nil?
303
-
304
- require "dry/validation/messages/i18n" if config.messages == :i18n
305
- end
306
- end
307
-
308
- # @since 0.6.0
309
- # @api private
310
- def __predicates
311
- mod = _predicates_module || Module.new { include Hanami::Validations::Predicates }
312
-
313
- _predicates.each do |p|
314
- mod.module_eval do
315
- predicate(p.name, &p.to_proc)
316
- end
317
- end
318
-
319
- mod
320
- end
321
-
322
- # @since 0.6.0
323
- # @api private
324
- def __messages
325
- result = _predicates.each_with_object({}) do |p, ret|
326
- ret[p.name] = p.message
327
- end
328
-
329
- # @api private
330
- Module.new do
331
- @@__messages = result # rubocop:disable Style/ClassVars
332
-
333
- # @api private
334
- def self.extended(base)
335
- base.instance_eval do
336
- def __messages
337
- Hash[en: {errors: @@__messages}]
338
- end
339
- end
340
- end
341
-
342
- # @api private
343
- def messages
344
- engine = super
345
-
346
- messages = if engine.respond_to?(:merge)
347
- engine
348
- else
349
- engine.messages
350
- end
351
-
352
- config.messages == :i18n ? messages : messages.merge(__messages)
353
- end
354
- end
75
+ def _validator
76
+ @_validator
355
77
  end
356
78
  end
357
79
 
@@ -360,17 +82,19 @@ module Hanami
360
82
  # @param input [#to_h] a set of input data
361
83
  #
362
84
  # @since 0.6.0
363
- def initialize(input = {})
364
- @input = input.to_h
85
+ def initialize(input)
86
+ @input = input
365
87
  end
366
88
 
367
89
  # Validates the object.
368
90
  #
369
- # @return [Dry::Validations::Result]
91
+ # @return [Hanami::Validations::Result]
370
92
  #
371
93
  # @since 0.2.4
372
94
  def validate
373
- self.class.schema.call(@input)
95
+ Result.new(
96
+ self.class._validator.call(@input)
97
+ )
374
98
  end
375
99
 
376
100
  # Returns a Hash with the defined attributes as symbolized keys, and their
@@ -380,7 +104,7 @@ module Hanami
380
104
  #
381
105
  # @since 0.1.0
382
106
  def to_h
383
- validate.output
107
+ validate.to_h
384
108
  end
385
109
  end
386
110
  end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/validation"
4
+
5
+ module Hanami
6
+ # @since 2.0.0
7
+ class Validator < Dry::Validation::Contract
8
+ end
9
+ end
metadata CHANGED
@@ -1,69 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hanami-validations
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.7
4
+ version: 2.0.0.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luca Guidi
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-01-06 00:00:00.000000000 Z
11
+ date: 2022-07-20 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: hanami-utils
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '1.3'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '1.3'
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: dry-validation
29
15
  requirement: !ruby/object:Gem::Requirement
30
16
  requirements:
31
17
  - - "~>"
32
18
  - !ruby/object:Gem::Version
33
- version: '0.11'
34
- - - "<"
35
- - !ruby/object:Gem::Version
36
- version: '0.12'
37
- type: :runtime
38
- prerelease: false
39
- version_requirements: !ruby/object:Gem::Requirement
40
- requirements:
41
- - - "~>"
42
- - !ruby/object:Gem::Version
43
- version: '0.11'
44
- - - "<"
45
- - !ruby/object:Gem::Version
46
- version: '0.12'
47
- - !ruby/object:Gem::Dependency
48
- name: dry-logic
49
- requirement: !ruby/object:Gem::Requirement
50
- requirements:
51
- - - "~>"
52
- - !ruby/object:Gem::Version
53
- version: 0.4.2
54
- - - "<"
55
- - !ruby/object:Gem::Version
56
- version: '0.5'
19
+ version: '1.6'
57
20
  type: :runtime
58
21
  prerelease: false
59
22
  version_requirements: !ruby/object:Gem::Requirement
60
23
  requirements:
61
24
  - - "~>"
62
25
  - !ruby/object:Gem::Version
63
- version: 0.4.2
64
- - - "<"
65
- - !ruby/object:Gem::Version
66
- version: '0.5'
26
+ version: '1.6'
67
27
  - !ruby/object:Gem::Dependency
68
28
  name: bundler
69
29
  requirement: !ruby/object:Gem::Requirement
@@ -116,16 +76,16 @@ dependencies:
116
76
  name: rubocop
117
77
  requirement: !ruby/object:Gem::Requirement
118
78
  requirements:
119
- - - '='
79
+ - - "~>"
120
80
  - !ruby/object:Gem::Version
121
- version: '0.81'
81
+ version: '1.0'
122
82
  type: :development
123
83
  prerelease: false
124
84
  version_requirements: !ruby/object:Gem::Requirement
125
85
  requirements:
126
- - - '='
86
+ - - "~>"
127
87
  - !ruby/object:Gem::Version
128
- version: '0.81'
88
+ version: '1.0'
129
89
  description: Validations mixin for Ruby objects and support for Hanami
130
90
  email:
131
91
  - me@lucaguidi.com
@@ -137,18 +97,16 @@ files:
137
97
  - LICENSE.md
138
98
  - README.md
139
99
  - hanami-validations.gemspec
140
- - lib/hanami-validations.rb
141
100
  - lib/hanami/validations.rb
142
101
  - lib/hanami/validations/form.rb
143
- - lib/hanami/validations/inline_predicate.rb
144
- - lib/hanami/validations/namespace.rb
145
- - lib/hanami/validations/predicates.rb
146
102
  - lib/hanami/validations/version.rb
103
+ - lib/hanami/validator.rb
147
104
  homepage: http://hanamirb.org
148
105
  licenses:
149
106
  - MIT
150
- metadata: {}
151
- post_install_message:
107
+ metadata:
108
+ rubygems_mfa_required: 'true'
109
+ post_install_message:
152
110
  rdoc_options: []
153
111
  require_paths:
154
112
  - lib
@@ -156,15 +114,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
156
114
  requirements:
157
115
  - - ">="
158
116
  - !ruby/object:Gem::Version
159
- version: 2.3.0
117
+ version: '3.0'
160
118
  required_rubygems_version: !ruby/object:Gem::Requirement
161
119
  requirements:
162
- - - ">="
120
+ - - ">"
163
121
  - !ruby/object:Gem::Version
164
- version: '0'
122
+ version: 1.3.1
165
123
  requirements: []
166
- rubygems_version: 3.2.2
167
- signing_key:
124
+ rubygems_version: 3.3.3
125
+ signing_key:
168
126
  specification_version: 4
169
127
  summary: Validations mixin for Ruby objects
170
128
  test_files: []