dry-validation 1.0.0.beta1 → 1.0.0.beta2

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: f6a47d27d49e9894cf283af7e4809cea07f45e5f8f3f52a180dd20d8c849b315
4
- data.tar.gz: 83f1e9b5ff94c4db24769624dd1552f0876be541926ffd57d43c2490757ab662
3
+ metadata.gz: 705706b2bc77cae54a87647ce3d85d685aa2fe619e40950533e1d96a513d1ca0
4
+ data.tar.gz: a0ad40a08b44475bafa4510707870603517145602e5567bb10cd39f98a1895af
5
5
  SHA512:
6
- metadata.gz: 67ab872380ecdc45fbe1efeb8cec95a03dff692aae2e74ca498483ceb7104b6a2d5cd78bdc23884d69d89665f110f79c3fa67285b97a40cc2c3625f9744bc34f
7
- data.tar.gz: f306b9dc73085526c485a7b18f2e33c83d08dd72922f1640bbc9b3b6ea0164ad1fbda752da0bb9b5d1f55dbd47c6ca6aa9ebef297035fd7adb22bb18be879c4e
6
+ metadata.gz: 7f2a5347e9b057d76cf9d99c0c313c7437133c1884e750a6c54d095e00f66eb600d7d79a033c2ba561a32c92b783c3153cbd8d88e62c715cd75e9d238f2a034a
7
+ data.tar.gz: 0a6312efffe80b0156da48da466a9c4384e0b636ef34a93587097592e72a9a2d72f9503e8aa6e556399fc8ad9a18399cc1e5fea2ddb9e66b6268509fcb796d4a
@@ -1,3 +1,31 @@
1
+ # v1.0.0.beta2 2019-04-04
2
+
3
+ ### Added
4
+
5
+ * Support for arbitrary meta-data in failures, ie:
6
+
7
+ ```ruby
8
+ class NewUserContract < Dry::Validation::Contract
9
+ params do
10
+ required(:login).filled(:string)
11
+ end
12
+
13
+ rule(:login) do
14
+ key.failure(text: 'is taken', code: 123) unless db.unique?(values[:login])
15
+ end
16
+ end
17
+ ```
18
+
19
+ Now your error hash will include `{ login: [{ text: 'is taken', code: 123 }] }` (solnic + flash-gordon)
20
+
21
+ ### Changed
22
+
23
+ * [BREAKING] `Error` was renamed to `Message` as it is a more generic concept (solnic)
24
+ * [BREAKING] `ErrorSet` was renamed to `MessageSet` for consistency (solnic)
25
+ * [BREAKING] `:monads` extension wraps entire result objects in `Success` or `Failure` (flash-gordon)
26
+
27
+ [Compare v1.0.0.beta1...v1.0.0.beta2](https://github.com/dry-rb/dry-validation/compare/v1.0.0.beta1...v1.0.0.beta2)
28
+
1
29
  # v1.0.0.beta1 2019-03-26
2
30
 
3
31
  ### Added
data/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  [gem]: https://rubygems.org/gems/dry-validation
2
2
  [travis]: https://travis-ci.org/dry-rb/dry-validation
3
3
  [codeclimate]: https://codeclimate.com/github/dry-rb/dry-validation
4
- [coveralls]: https://coveralls.io/r/dry-rb/dry-validation
4
+ [chat]: https://dry-rb.zulipchat.com
5
5
  [inchpages]: http://inch-ci.org/github/dry-rb/dry-validation
6
6
 
7
- # dry-validation [![Join the chat at https://gitter.im/dry-rb/chat](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/dry-rb/chat)
7
+ # dry-validation [![Join the chat at https://dry-rb.zulipchat.com](https://img.shields.io/badge/dry--rb-join%20chat-%23346b7a.svg)][chat]
8
8
 
9
9
  [![Gem Version](https://badge.fury.io/rb/dry-validation.svg)][gem]
10
10
  [![Build Status](https://travis-ci.org/dry-rb/dry-validation.svg?branch=master)][travis]
@@ -11,7 +11,6 @@ require 'dry/validation/rule'
11
11
  require 'dry/validation/evaluator'
12
12
  require 'dry/validation/messages/resolver'
13
13
  require 'dry/validation/result'
14
- require 'dry/validation/error'
15
14
  require 'dry/validation/contract/class_interface'
16
15
 
17
16
  module Dry
@@ -27,7 +27,7 @@ module Dry
27
27
  #
28
28
  # @api public
29
29
  def to_monad
30
- success? ? Success(to_h) : Failure(self)
30
+ success? ? Success(self) : Failure(self)
31
31
  end
32
32
  end
33
33
  end
@@ -1,15 +1,17 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'dry/equalizer'
4
+
5
+ require 'dry/schema/constants'
4
6
  require 'dry/schema/message'
5
7
 
6
8
  module Dry
7
9
  module Validation
8
- # Error message
10
+ # Message message
9
11
  #
10
12
  # @api public
11
- class Error < Schema::Message
12
- include Dry::Equalizer(:text, :path)
13
+ class Message < Schema::Message
14
+ include Dry::Equalizer(:text, :path, :meta)
13
15
 
14
16
  # @!attribute [r] text
15
17
  # @return [String] text The error message text
@@ -19,29 +21,36 @@ module Dry
19
21
  # @return [Array<Symbol, Integer>] path The path to the value with the error
20
22
  attr_reader :path
21
23
 
24
+ # @!attribute [r] meta
25
+ # @return [Hash] meta Optional hash with meta-data
26
+ attr_reader :meta
27
+
22
28
  # @api public
23
- class Localized < Error
29
+ class Localized < Message
24
30
  # @api public
25
31
  def evaluate(**opts)
26
- Error.new(text.(opts), path: path)
32
+ evaluated_text, rest = text.(opts)
33
+ Message.new(evaluated_text, path: path, meta: rest.merge(meta))
27
34
  end
28
35
  end
29
36
 
30
37
  # Build an error
31
38
  #
32
- # @return [Error, Error::Localized]
39
+ # @return [Message, Message::Localized]
33
40
  #
34
41
  # @api public
35
- def self.[](text, path)
36
- text.respond_to?(:call) ? Localized.new(text, path: path) : Error.new(text, path: path)
42
+ def self.[](text, path, meta)
43
+ klass = text.respond_to?(:call) ? Localized : Message
44
+ klass.new(text, path: path, meta: meta)
37
45
  end
38
46
 
39
47
  # Initialize a new error object
40
48
  #
41
49
  # @api private
42
- def initialize(text, path:)
50
+ def initialize(text, path:, meta: EMPTY_HASH)
43
51
  @text = text
44
52
  @path = Array(path)
53
+ @meta = meta
45
54
  end
46
55
 
47
56
  # Check if this is a base error not associated with any key
@@ -3,17 +3,17 @@
3
3
  require 'dry/schema/message_set'
4
4
 
5
5
  require 'dry/validation/constants'
6
- require 'dry/validation/error'
6
+ require 'dry/validation/message'
7
7
 
8
8
  module Dry
9
9
  module Validation
10
- # ErrorSet is a specialized message set for handling validation errors
10
+ # MessageSet is a specialized message set for handling validation messages
11
11
  #
12
12
  # @api public
13
- class ErrorSet < Schema::MessageSet
13
+ class MessageSet < Schema::MessageSet
14
14
  # @!attribute [r] source
15
15
  # Return the source set of messages used to produce final evaluated messages
16
- # @return [Array<Error, Error::Localized, Schema::Message>]
16
+ # @return [Array<Message, Message::Localized, Schema::Message>]
17
17
  # @api private
18
18
  attr_reader :source_messages
19
19
 
@@ -29,54 +29,54 @@ module Dry
29
29
  super
30
30
  end
31
31
 
32
- # Return a new error set using updated options
32
+ # Return a new message set using updated options
33
33
  #
34
- # @return [ErrorSet]
34
+ # @return [MessageSet]
35
35
  #
36
36
  # @api private
37
37
  def with(other, new_options = EMPTY_HASH)
38
38
  return self if new_options.empty?
39
39
 
40
40
  self.class.new(
41
- other + select { |err| err.is_a?(Error) },
41
+ other + select { |err| err.is_a?(Message) },
42
42
  options.merge(source: source_messages, **new_options)
43
43
  ).freeze
44
44
  end
45
45
 
46
- # Add a new error
46
+ # Add a new message
47
47
  #
48
48
  # This is used when result is being prepared
49
49
  #
50
- # @return [ErrorSet]
50
+ # @return [MessageSet]
51
51
  #
52
52
  # @api private
53
- def add(error)
54
- source_messages << error
55
- messages << error
53
+ def add(message)
54
+ source_messages << message
55
+ messages << message
56
56
  initialize_placeholders!
57
57
  self
58
58
  end
59
59
 
60
- # Filter error set using provided predicates
60
+ # Filter message set using provided predicates
61
61
  #
62
- # This method is open to any predicate because errors can be anything that
62
+ # This method is open to any predicate because messages can be anything that
63
63
  # implements Message API, thus they can implement whatever predicates you
64
64
  # may need.
65
65
  #
66
- # @example get a list of base errors
67
- # error_set = contract.(input).error_set
68
- # error_set.filter(:base?)
66
+ # @example get a list of base messages
67
+ # message_set = contract.(input).message_set
68
+ # message_set.filter(:base?)
69
69
  #
70
70
  # @param [Array<Symbol>] *predicates
71
71
  #
72
- # @return [ErrorSet]
72
+ # @return [MessageSet]
73
73
  #
74
74
  # @api public
75
75
  def filter(*predicates)
76
- errors = select { |e|
77
- predicates.all? { |predicate| e.respond_to?(predicate) && e.public_send(predicate) }
76
+ messages = select { |msg|
77
+ predicates.all? { |predicate| msg.respond_to?(predicate) && msg.public_send(predicate) }
78
78
  }
79
- self.class.new(errors)
79
+ self.class.new(messages)
80
80
  end
81
81
 
82
82
  # @api private
@@ -101,7 +101,7 @@ module Dry
101
101
  def messages_map
102
102
  @messages_map ||= reduce(placeholders) { |hash, msg|
103
103
  node = msg.path.reduce(hash) { |a, e| a.is_a?(Hash) ? a[e] : a.last[e] }
104
- (node.size > 1 ? node[0] : node) << msg.to_s
104
+ (node.size > 1 ? node[0] : node) << msg.dump
105
105
  hash
106
106
  }
107
107
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'dry/validation/message'
4
+
3
5
  module Dry
4
6
  module Validation
5
7
  module Messages
@@ -23,19 +25,23 @@ module Dry
23
25
  @locale = locale
24
26
  end
25
27
 
26
- # Resolve Error object from provided args and path
28
+ # Resolve Message object from provided args and path
27
29
  #
28
30
  # This is used internally by contracts when rules are applied
29
31
  #
30
- # @return [Error, Error::Localized]
32
+ # @return [Message, Message::Localized]
31
33
  #
32
34
  # @api public
33
- def call(message:, tokens:, path:)
35
+ def call(message:, tokens:, path:, meta: EMPTY_HASH)
34
36
  case message
35
37
  when Symbol
36
- Error[->(**opts) { message(message, path: path, tokens: tokens, **opts) }, path]
38
+ Message[->(**opts) { message(message, path: path, tokens: tokens, **opts) }, path, meta]
37
39
  when String
38
- Error[message, path]
40
+ Message[message, path, meta]
41
+ when Hash
42
+ meta = message.dup
43
+ text = meta.delete(:text)
44
+ call(message: text, tokens: tokens, path: path, meta: meta)
39
45
  end
40
46
  end
41
47
  alias_method :[], :call
@@ -50,10 +56,10 @@ module Dry
50
56
  msg_opts = tokens.merge(path: keys, locale: locale)
51
57
 
52
58
  if keys.empty?
53
- template = messages["rules.#{rule}", msg_opts]
59
+ template, meta = messages["rules.#{rule}", msg_opts]
54
60
  else
55
- template = messages[rule, msg_opts.merge(path: keys.join(DOT))]
56
- template ||= messages[rule, msg_opts.merge(path: keys.last)]
61
+ template, meta = messages[rule, msg_opts.merge(path: keys.join(DOT))]
62
+ template, meta = messages[rule, msg_opts.merge(path: keys.last)] unless template
57
63
  end
58
64
 
59
65
  unless template
@@ -64,7 +70,7 @@ module Dry
64
70
 
65
71
  text = template.(template.data(tokens))
66
72
 
67
- full ? "#{messages.rule(keys.last, msg_opts)} #{text}" : text
73
+ [full ? "#{messages.rule(keys.last, msg_opts)} #{text}" : text, meta]
68
74
  end
69
75
  end
70
76
  end
@@ -3,7 +3,7 @@
3
3
  require 'dry/equalizer'
4
4
 
5
5
  require 'dry/validation/constants'
6
- require 'dry/validation/error_set'
6
+ require 'dry/validation/message_set'
7
7
 
8
8
  module Dry
9
9
  module Validation
@@ -45,7 +45,7 @@ module Dry
45
45
 
46
46
  # Get error set
47
47
  #
48
- # @return [ErrorSet]
48
+ # @return [MessageSet]
49
49
  #
50
50
  # @api public
51
51
  def errors(new_options = EMPTY_HASH)
@@ -134,7 +134,7 @@ module Dry
134
134
 
135
135
  # @api private
136
136
  def initialize_errors(options = self.options)
137
- ErrorSet.new(schema_errors(options), options)
137
+ MessageSet.new(schema_errors(options), options)
138
138
  end
139
139
 
140
140
  # @api private
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Dry
4
4
  module Validation
5
- VERSION = '1.0.0.beta1'
5
+ VERSION = '1.0.0.beta2'
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.0.0.beta1
4
+ version: 1.0.0.beta2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotr Solnica
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-03-26 00:00:00.000000000 Z
11
+ date: 2019-04-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -76,22 +76,22 @@ dependencies:
76
76
  name: dry-schema
77
77
  requirement: !ruby/object:Gem::Requirement
78
78
  requirements:
79
- - - "~>"
80
- - !ruby/object:Gem::Version
81
- version: '0.3'
82
79
  - - ">="
83
80
  - !ruby/object:Gem::Version
84
- version: '0.4'
81
+ version: '0.5'
82
+ - - "~>"
83
+ - !ruby/object:Gem::Version
84
+ version: '0.5'
85
85
  type: :runtime
86
86
  prerelease: false
87
87
  version_requirements: !ruby/object:Gem::Requirement
88
88
  requirements:
89
- - - "~>"
90
- - !ruby/object:Gem::Version
91
- version: '0.3'
92
89
  - - ">="
93
90
  - !ruby/object:Gem::Version
94
- version: '0.4'
91
+ version: '0.5'
92
+ - - "~>"
93
+ - !ruby/object:Gem::Version
94
+ version: '0.5'
95
95
  - !ruby/object:Gem::Dependency
96
96
  name: bundler
97
97
  requirement: !ruby/object:Gem::Requirement
@@ -150,10 +150,10 @@ files:
150
150
  - lib/dry/validation/constants.rb
151
151
  - lib/dry/validation/contract.rb
152
152
  - lib/dry/validation/contract/class_interface.rb
153
- - lib/dry/validation/error.rb
154
- - lib/dry/validation/error_set.rb
155
153
  - lib/dry/validation/evaluator.rb
156
154
  - lib/dry/validation/extensions/monads.rb
155
+ - lib/dry/validation/message.rb
156
+ - lib/dry/validation/message_set.rb
157
157
  - lib/dry/validation/messages/resolver.rb
158
158
  - lib/dry/validation/result.rb
159
159
  - lib/dry/validation/rule.rb