dry-validation 0.1.0 → 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +969 -1
  3. data/LICENSE +1 -1
  4. data/README.md +19 -286
  5. data/config/errors.yml +4 -35
  6. data/dry-validation.gemspec +38 -22
  7. data/lib/dry/validation/config.rb +24 -0
  8. data/lib/dry/validation/constants.rb +43 -0
  9. data/lib/dry/validation/contract/class_interface.rb +230 -0
  10. data/lib/dry/validation/contract.rb +173 -0
  11. data/lib/dry/validation/evaluator.rb +233 -0
  12. data/lib/dry/validation/extensions/hints.rb +67 -0
  13. data/lib/dry/validation/extensions/monads.rb +34 -0
  14. data/lib/dry/validation/extensions/predicates_as_macros.rb +75 -0
  15. data/lib/dry/validation/failures.rb +70 -0
  16. data/lib/dry/validation/function.rb +43 -0
  17. data/lib/dry/validation/macro.rb +38 -0
  18. data/lib/dry/validation/macros.rb +104 -0
  19. data/lib/dry/validation/message.rb +100 -0
  20. data/lib/dry/validation/message_set.rb +97 -0
  21. data/lib/dry/validation/messages/resolver.rb +129 -0
  22. data/lib/dry/validation/result.rb +206 -38
  23. data/lib/dry/validation/rule.rb +116 -106
  24. data/lib/dry/validation/schema_ext.rb +19 -0
  25. data/lib/dry/validation/values.rb +108 -0
  26. data/lib/dry/validation/version.rb +3 -1
  27. data/lib/dry/validation.rb +55 -7
  28. data/lib/dry-validation.rb +3 -1
  29. metadata +80 -106
  30. data/.gitignore +0 -8
  31. data/.rspec +0 -3
  32. data/.rubocop.yml +0 -16
  33. data/.rubocop_todo.yml +0 -7
  34. data/.travis.yml +0 -29
  35. data/Gemfile +0 -11
  36. data/Rakefile +0 -12
  37. data/examples/basic.rb +0 -21
  38. data/examples/nested.rb +0 -30
  39. data/examples/rule_ast.rb +0 -33
  40. data/lib/dry/validation/error.rb +0 -43
  41. data/lib/dry/validation/error_compiler.rb +0 -116
  42. data/lib/dry/validation/messages.rb +0 -71
  43. data/lib/dry/validation/predicate.rb +0 -39
  44. data/lib/dry/validation/predicate_set.rb +0 -22
  45. data/lib/dry/validation/predicates.rb +0 -88
  46. data/lib/dry/validation/rule_compiler.rb +0 -57
  47. data/lib/dry/validation/schema/definition.rb +0 -15
  48. data/lib/dry/validation/schema/key.rb +0 -39
  49. data/lib/dry/validation/schema/rule.rb +0 -28
  50. data/lib/dry/validation/schema/value.rb +0 -31
  51. data/lib/dry/validation/schema.rb +0 -74
  52. data/rakelib/rubocop.rake +0 -18
  53. data/spec/fixtures/errors.yml +0 -4
  54. data/spec/integration/custom_error_messages_spec.rb +0 -35
  55. data/spec/integration/custom_predicates_spec.rb +0 -57
  56. data/spec/integration/validation_spec.rb +0 -118
  57. data/spec/shared/predicates.rb +0 -31
  58. data/spec/spec_helper.rb +0 -18
  59. data/spec/unit/error_compiler_spec.rb +0 -165
  60. data/spec/unit/predicate_spec.rb +0 -37
  61. data/spec/unit/predicates/empty_spec.rb +0 -38
  62. data/spec/unit/predicates/eql_spec.rb +0 -21
  63. data/spec/unit/predicates/exclusion_spec.rb +0 -35
  64. data/spec/unit/predicates/filled_spec.rb +0 -38
  65. data/spec/unit/predicates/format_spec.rb +0 -21
  66. data/spec/unit/predicates/gt_spec.rb +0 -40
  67. data/spec/unit/predicates/gteq_spec.rb +0 -40
  68. data/spec/unit/predicates/inclusion_spec.rb +0 -35
  69. data/spec/unit/predicates/int_spec.rb +0 -34
  70. data/spec/unit/predicates/key_spec.rb +0 -29
  71. data/spec/unit/predicates/lt_spec.rb +0 -40
  72. data/spec/unit/predicates/lteq_spec.rb +0 -40
  73. data/spec/unit/predicates/max_size_spec.rb +0 -49
  74. data/spec/unit/predicates/min_size_spec.rb +0 -49
  75. data/spec/unit/predicates/nil_spec.rb +0 -28
  76. data/spec/unit/predicates/size_spec.rb +0 -49
  77. data/spec/unit/predicates/str_spec.rb +0 -32
  78. data/spec/unit/rule/each_spec.rb +0 -20
  79. data/spec/unit/rule/key_spec.rb +0 -27
  80. data/spec/unit/rule/set_spec.rb +0 -32
  81. data/spec/unit/rule/value_spec.rb +0 -42
  82. data/spec/unit/rule_compiler_spec.rb +0 -86
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2014 Ruby Object Mapper
3
+ Copyright (c) 2015-2021 dry-rb team
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy of
6
6
  this software and associated documentation files (the "Software"), to deal in
data/README.md CHANGED
@@ -1,296 +1,29 @@
1
- # dry-validation <a href="https://gitter.im/dryrb/chat" target="_blank">![Join the chat at https://gitter.im/dryrb/chat](https://badges.gitter.im/Join%20Chat.svg)</a>
1
+ <!--- this file is synced from dry-rb/template-gem project -->
2
+ [gem]: https://rubygems.org/gems/dry-validation
3
+ [actions]: https://github.com/dry-rb/dry-validation/actions
4
+ [codacy]: https://www.codacy.com/gh/dry-rb/dry-validation
5
+ [chat]: https://dry-rb.zulipchat.com
6
+ [inchpages]: http://inch-ci.org/github/dry-rb/dry-validation
2
7
 
3
- <a href="https://rubygems.org/gems/dry-validation" target="_blank">![Gem Version](https://badge.fury.io/rb/dry-validation.svg)</a>
4
- <a href="https://travis-ci.org/dryrb/dry-validation" target="_blank">![Build Status](https://travis-ci.org/dryrb/dry-validation.svg?branch=master)</a>
5
- <a href="https://gemnasium.com/dryrb/dry-validation" target="_blank">![Dependency Status](https://gemnasium.com/dryrb/dry-validation.svg)</a>
6
- <a href="https://codeclimate.com/github/dryrb/dry-validation" target="_blank">![Code Climate](https://codeclimate.com/github/dryrb/dry-validation/badges/gpa.svg)</a>
7
- <a href="http://inch-ci.org/github/dryrb/dry-validation" target="_blank">![Documentation Status](http://inch-ci.org/github/dryrb/dry-validation.svg?branch=master&style=flat)</a>
8
+ # dry-validation [![Join the chat at https://dry-rb.zulipchat.com](https://img.shields.io/badge/dry--rb-join%20chat-%23346b7a.svg)][chat]
8
9
 
9
- Data validation library based on predicate logic and rule composition.
10
+ [![Gem Version](https://badge.fury.io/rb/dry-validation.svg)][gem]
11
+ [![CI Status](https://github.com/dry-rb/dry-validation/workflows/ci/badge.svg)][actions]
12
+ [![Codacy Badge](https://api.codacy.com/project/badge/Grade/f30e3ff5ec304c55a73868cdbf055c67)][codacy]
13
+ [![Codacy Badge](https://api.codacy.com/project/badge/Coverage/f30e3ff5ec304c55a73868cdbf055c67)][codacy]
14
+ [![Inline docs](http://inch-ci.org/github/dry-rb/dry-validation.svg?branch=master)][inchpages]
10
15
 
11
- ## Overview
16
+ ## Links
12
17
 
13
- Unlike other, well known, validation solutions in Ruby, `dry-validation` takes
14
- a different approach and focuses a lot on explicitness, clarity and preciseness
15
- of validation logic. It is designed to work with any data input, whether it's a
16
- simple hash, an array or a complex object with deeply nested data.
18
+ * [User documentation](https://dry-rb.org/gems/dry-validation)
19
+ * [API documentation](http://rubydoc.info/gems/dry-validation)
17
20
 
18
- It is based on a simple idea that each validation is encapsulated by a simple,
19
- stateless predicate, that receives some input and returns either `true` or `false`.
21
+ ## Supported Ruby versions
20
22
 
21
- Those predicates are encapsulated by `rules` which can be composed together using
22
- `predicate logic`. This means you can use the common logic operators to build up
23
- a validation `schema`.
23
+ This library officially supports the following Ruby versions:
24
24
 
25
- It's very explicit, powerful and extendible.
26
-
27
- Validations can be described with great precision, `dry-validation` eliminates
28
- ambigious concepts like `presence` validation where we can't really say whether
29
- some attribute or key is *missing* or it's just that the value is `nil`.
30
-
31
- There's also the concept of type-safety, completely missing in other validation
32
- libraries, which is quite important and useful. It means you can compose a validation
33
- that does rely on the type of a given value. In example it makes no sense to validate
34
- each element of an array when it turns out to be an empty string.
35
-
36
- ## The DSL
37
-
38
- The core of `dry-validation` is rules composition and predicate logic. The DSL
39
- is a simple front-end for that. It only allows you to define the rules by using
40
- predicate identifiers. There are no magical options, conditionals and custom
41
- validation blocks known from other libraries. The focus is on pure validation
42
- logic.
43
-
44
- ## Examples
45
-
46
- ### Basic
47
-
48
- Here's a basic example where we validate following things:
49
-
50
- * The input *must have a key* called `:email`
51
- * Provided the email key is present, its value *must be filled*
52
- * The input *must have a key* called `:age`
53
- * Provided the age key is present, its value *must be an integer* and it *must be greater than 18*
54
-
55
- This can be easily expressed through the DSL:
56
-
57
- ``` ruby
58
- require 'dry-validation'
59
-
60
- class Schema < Dry::Validation::Schema
61
- key(:email) { |email| email.filled? }
62
-
63
- key(:age) do |age|
64
- age.int? & age.gt?(18)
65
- end
66
- end
67
-
68
- schema = Schema.new
69
-
70
- errors = schema.messages(email: 'jane@doe.org', age: 19)
71
-
72
- puts errors.inspect
73
- # []
74
-
75
- errors = schema.messages(email: nil, age: 19)
76
-
77
- puts errors.inspect
78
- # [[:email, ["email must be filled"]]]
79
- ```
80
-
81
- A couple of remarks:
82
-
83
- * `key` assumes that we want to use the `:key?` predicate to check the existance of that key
84
- * `age.gt?(18)` translates to calling a predicate like this: `schema[:gt?].(18, age)`
85
- * `age.int? & age.gt?(18)` is a conjunction, so we don't bother about `gt?` unless `int?` returns `true`
86
- * You can also use `|` for disjunction
87
- * Schema object does not carry the input as its state, nor does it know how to access the input values, we
88
- pass the input to `call` and get error set as the response
89
-
90
- ### Nested Hash
91
-
92
- We are free to define validations for anything, including deeply nested structures:
93
-
94
- ``` ruby
95
- require 'dry-validation'
96
-
97
- class Schema < Dry::Validation::Schema
98
- key(:address) do |address|
99
- address.key(:city) do |city|
100
- city.min_size?(3)
101
- end
102
-
103
- address.key(:street) do |street|
104
- street.filled?
105
- end
106
-
107
- address.key(:country) do |country|
108
- country.key(:name, &:filled?)
109
- country.key(:code, &:filled?)
110
- end
111
- end
112
- end
113
-
114
- schema = Schema.new
115
-
116
- errors = schema.messages({})
117
-
118
- puts errors.inspect
119
- # [[:address, ["address is missing"]]]
120
-
121
- errors = schema.messages(address: { city: 'NYC' })
122
-
123
- puts errors.inspect
124
- # [[:address, [[:street, ["street is missing"]], [:country, ["country is missing"]]]]]
125
- ```
126
-
127
- ### Defining Custom Predicates
128
-
129
- You can simply define predicate methods on your schema object:
130
-
131
- ``` ruby
132
- class Schema < Dry::Validation::Schema
133
- key(:email) { |value| value.str? & value.email? }
134
-
135
- def email?(value)
136
- ! /magical-regex-that-matches-emails/.match(value).nil?
137
- end
138
- end
139
- ```
140
-
141
- You can also re-use a predicate container across multiple schemas:
142
-
143
- ``` ruby
144
- module MyPredicates
145
- include Dry::Validation::Predicates
146
-
147
- predicate(:email?) do |input|
148
- ! /magical-regex-that-matches-emails/.match(value).nil?
149
- end
150
- end
151
-
152
- class Schema < Dry::Validation::Schema
153
- configure do |config|
154
- config.predicates = MyPredicates
155
- end
156
-
157
- key(:email) { |value| value.str? & value.email? }
158
- end
159
- ```
160
-
161
- ## List of Built-In Predicates
162
-
163
- * `empty?`
164
- * `eql?`
165
- * `exclusion?`
166
- * `filled?`
167
- * `format?`
168
- * `gt?`
169
- * `gteq?`
170
- * `inclusion?`
171
- * `int?`
172
- * `key?`
173
- * `lt?`
174
- * `lteq?`
175
- * `max_size?`
176
- * `min_size?`
177
- * `nil?`
178
- * `size?`
179
- * `str?`
180
-
181
- ## Error Messages
182
-
183
- By default `dry-validation` comes with a set of pre-defined error messages for
184
- every built-in predicate. They are defined in [a yaml file](https://github.com/dryrb/dry-validation/blob/master/config/errors.yml)
185
- which is shipped with the gem.
186
-
187
- You can provide your own messages and configure your schemas to use it like that:
188
-
189
- ``` ruby
190
- class Schema < Dry::Validation::Schema
191
- configure { |config| config.messages_file = '/path/to/my/errors.yml' }
192
- end
193
- ```
194
-
195
- You can also provide a namespace per-schema that will be used by default:
196
-
197
- ``` ruby
198
- class Schema < Dry::Validation::Schema
199
- configure { |config| config.namespace = :user }
200
- end
201
- ```
202
-
203
- Lookup rules:
204
-
205
- ``` yaml
206
- filled?: "%{name} must be filled"
207
-
208
- attributes:
209
- email:
210
- filled?: "the email is missing"
211
-
212
- user:
213
- filled?: "%{name} name cannot be blank"
214
-
215
- attributes:
216
- address:
217
- filled?: "You gotta tell us where you live"
218
- ```
219
-
220
- Given the yaml file above, messages lookup works as follows:
221
-
222
- ``` ruby
223
- messages = Dry::Validation::Messages.load('/path/to/our/errors.yml')
224
-
225
- messages.lookup(:filled?, :age) # => "age must be filled"
226
- messages.lookup(:filled?, :address) # => "address must be filled"
227
- messages.lookup(:filled?, :email) # => "the email is missing"
228
-
229
- # with namespaced messages
230
- user_messages = messages.namespaced(:user)
231
-
232
- user_messages.lookup(:filled?, :age) # "age cannot be blank"
233
- user_messages.lookup(:filled?, :address) # "You gotta tell us where you live"
234
- ```
235
-
236
- By configuring `messages_file` and/or `namespace` in a schema, default messages
237
- are going to be automatically merged with your overrides and/or namespaced.
238
-
239
- ## I18n Integration
240
-
241
- Coming (very) soon...
242
-
243
- ## Rule AST
244
-
245
- Internally, `dry-validation` uses a simple AST representation of rules and errors
246
- to produce rule objects and error messages. If you would like to programatically
247
- generate rules, it is a very simple process:
248
-
249
- ``` ruby
250
- ast = [
251
- [
252
- :and,
253
- [
254
- [:key, [:age, [:predicate, [:key?, []]]]],
255
- [
256
- :and,
257
- [
258
- [:val, [:age, [:predicate, [:filled?, []]]]],
259
- [:val, [:age, [:predicate, [:gt?, [18]]]]]
260
- ]
261
- ]
262
- ]
263
- ]
264
- ]
265
-
266
- compiler = Dry::Validation::RuleCompiler.new(Dry::Validation::Predicates)
267
-
268
- # compile an array of rule objects
269
- rules = compiler.call(ast)
270
-
271
- puts rules.inspect
272
- # [
273
- # #<Dry::Validation::Rule::Conjunction
274
- # left=#<Dry::Validation::Rule::Key name=:age predicate=#<Dry::Validation::Predicate id=:key?>>
275
- # right=#<Dry::Validation::Rule::Conjunction
276
- # left=#<Dry::Validation::Rule::Value name=:age predicate=#<Dry::Validation::Predicate id=:filled?>>
277
- # right=#<Dry::Validation::Rule::Value name=:age predicate=#<Dry::Validation::Predicate id=:gt?>>>>
278
- # ]
279
-
280
- # dump it back to ast
281
- puts rules.map(&:to_ary).inspect
282
- # [[:and, [:key, [:age, [:predicate, [:key?, [:age]]]]], [[:and, [:val, [:age, [:predicate, [:filled?, []]]]], [[:val, [:age, [:predicate, [:gt?, [18]]]]]]]]]]
283
- ```
284
-
285
- Complete docs for the AST format are coming soon, for now please refer to
286
- [this spec](https://github.com/dryrb/dry-validation/blob/master/spec/unit/rule_compiler_spec.rb).
287
-
288
- ## Status and Roadmap
289
-
290
- This library is in a very early stage of development but you are encauraged to
291
- try it out and provide feedback.
292
-
293
- For planned features check out [the issues](https://github.com/dryrb/dry-validation/labels/feature).
25
+ * MRI `>= 2.7.0`
26
+ * jruby `>= 9.3` (postponed until 2.7 is supported)
294
27
 
295
28
  ## License
296
29
 
data/config/errors.yml CHANGED
@@ -1,35 +1,4 @@
1
- empty?: "%{name} cannot be empty"
2
-
3
- exclusion?: "%{name} must not be one of: %{list}"
4
-
5
- eql?: "%{name} must be equal to %{eql_value}"
6
-
7
- filled?: "%{name} must be filled"
8
-
9
- format?: "%{name} is in invalid format"
10
-
11
- gt?: "%{name} must be greater than %{num} (%{value} was given)"
12
-
13
- gteq?: "%{name} must be greater than or equal to %{num}"
14
-
15
- inclusion?: "%{name} must be one of: %{list}"
16
-
17
- int?: "%{name} must be an integer"
18
-
19
- key?: "%{name} is missing"
20
-
21
- lt?: "%{name} must be less than %{num} (%{value} was given)"
22
-
23
- lteq?: "%{name} must be less than or equal to %{num}"
24
-
25
- max_size?: "%{name} size cannot be greater than %{num}"
26
-
27
- min_size?: "%{name} size cannot be less than %{num}"
28
-
29
- nil?: "%{name} cannot be nil"
30
-
31
- size?:
32
- range: "%{name} size must be within %{left} - %{right}"
33
- default: "%{name} size must be %{num}"
34
-
35
- str?: "%{name} must be a string"
1
+ en:
2
+ dry_validation:
3
+ errors:
4
+ acceptance: "must accept %{key}"
@@ -1,25 +1,41 @@
1
- # coding: utf-8
2
- require File.expand_path('../lib/dry/validation/version', __FILE__)
1
+ # frozen_string_literal: true
2
+
3
+ # this file is synced from dry-rb/template-gem project
4
+
5
+ lib = File.expand_path("lib", __dir__)
6
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
7
+ require "dry/validation/version"
3
8
 
4
9
  Gem::Specification.new do |spec|
5
- spec.name = 'dry-validation'
6
- spec.version = Dry::Validation::VERSION
7
- spec.authors = ['Andy Holland', 'Piotr Solnica']
8
- spec.email = ['andyholland1991@aol.com', 'piotr.solnica@gmail.com']
9
- spec.summary = 'A simple validation library'
10
- spec.homepage = 'https://github.com/dryrb/dry-validation'
11
- spec.license = 'MIT'
12
-
13
- spec.files = `git ls-files -z`.split("\x0")
14
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
15
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
16
- spec.require_paths = ['lib']
17
-
18
- spec.add_runtime_dependency 'dry-configurable', '~> 0.1'
19
- spec.add_runtime_dependency 'dry-container', '~> 0.2', '>= 0.2.6'
20
- spec.add_runtime_dependency 'dry-equalizer', '~> 0.2'
21
-
22
- spec.add_development_dependency 'bundler'
23
- spec.add_development_dependency 'rake'
24
- spec.add_development_dependency 'rspec'
10
+ spec.name = "dry-validation"
11
+ spec.authors = ["Piotr Solnica"]
12
+ spec.email = ["piotr.solnica@gmail.com"]
13
+ spec.license = "MIT"
14
+ spec.version = Dry::Validation::VERSION.dup
15
+
16
+ spec.summary = "Validation library"
17
+ spec.description = spec.summary
18
+ spec.homepage = "https://dry-rb.org/gems/dry-validation"
19
+ spec.files = Dir["CHANGELOG.md", "LICENSE", "README.md", "dry-validation.gemspec", "lib/**/*", "config/*.yml"]
20
+ spec.bindir = "bin"
21
+ spec.executables = []
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
25
+ spec.metadata["changelog_uri"] = "https://github.com/dry-rb/dry-validation/blob/master/CHANGELOG.md"
26
+ spec.metadata["source_code_uri"] = "https://github.com/dry-rb/dry-validation"
27
+ spec.metadata["bug_tracker_uri"] = "https://github.com/dry-rb/dry-validation/issues"
28
+
29
+ spec.required_ruby_version = ">= 2.7.0"
30
+
31
+ # to update dependencies edit project.yml
32
+ spec.add_runtime_dependency "concurrent-ruby", "~> 1.0"
33
+ spec.add_runtime_dependency "dry-container", "~> 0.7", ">= 0.7.1"
34
+ spec.add_runtime_dependency "dry-core", "~> 0.5", ">= 0.5"
35
+ spec.add_runtime_dependency "dry-initializer", "~> 3.0"
36
+ spec.add_runtime_dependency "dry-schema", "~> 1.9", ">= 1.9.1"
37
+
38
+ spec.add_development_dependency "bundler"
39
+ spec.add_development_dependency "rake"
40
+ spec.add_development_dependency "rspec"
25
41
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/schema/config"
4
+ require "dry/validation/macros"
5
+
6
+ module Dry
7
+ module Validation
8
+ # Configuration for contracts
9
+ #
10
+ # @see Contract#config
11
+ #
12
+ # @api public
13
+ class Config < Schema::Config
14
+ setting :macros, default: Macros::Container.new, constructor: :dup.to_proc
15
+
16
+ # @api private
17
+ def dup
18
+ config = super
19
+ config.macros = macros.dup
20
+ config
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "pathname"
4
+ require "dry/core/constants"
5
+
6
+ module Dry
7
+ module Validation
8
+ include Dry::Core::Constants
9
+
10
+ DOT = "."
11
+
12
+ # Root path is used for base errors in hash representation of error messages
13
+ ROOT_PATH = [nil].freeze
14
+
15
+ # Path to the default errors locale file
16
+ DEFAULT_ERRORS_NAMESPACE = "dry_validation"
17
+
18
+ # Path to the default errors locale file
19
+ DEFAULT_ERRORS_PATH = Pathname(__FILE__).join("../../../../config/errors.yml").realpath.freeze
20
+
21
+ # Mapping for block kwarg options used by block_options
22
+ #
23
+ # @see Rule#block_options
24
+ BLOCK_OPTIONS_MAPPINGS = Hash.new { |_, key| key }.update(context: :_context).freeze
25
+
26
+ # Error raised when `rule` specifies one or more keys that the schema doesn't specify
27
+ InvalidKeysError = Class.new(StandardError)
28
+
29
+ # Error raised when a localized message was not found
30
+ MissingMessageError = Class.new(StandardError)
31
+
32
+ # Error raised when trying to define a schema in a contract class that already has a schema
33
+ DuplicateSchemaError = Class.new(StandardError)
34
+
35
+ # Error raised during initialization of a contract that has no schema defined
36
+ SchemaMissingError = Class.new(StandardError) do
37
+ # @api private
38
+ def initialize(klass)
39
+ super("#{klass} cannot be instantiated without a schema defined")
40
+ end
41
+ end
42
+ end
43
+ end