reform 2.2.4 → 2.3.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +5 -1
- data/.travis.yml +11 -6
- data/Appraisals +8 -0
- data/CHANGES.md +57 -4
- data/CONTRIBUTING.md +31 -0
- data/Gemfile +2 -16
- data/ISSUE_TEMPLATE.md +25 -0
- data/LICENSE.txt +1 -1
- data/README.md +5 -7
- data/Rakefile +16 -9
- data/gemfiles/0.13.0.gemfile +8 -0
- data/gemfiles/1.5.0.gemfile +9 -0
- data/lib/reform.rb +1 -0
- data/lib/reform/contract.rb +7 -17
- data/lib/reform/contract/custom_error.rb +41 -0
- data/lib/reform/contract/validate.rb +53 -23
- data/lib/reform/errors.rb +61 -0
- data/lib/reform/form.rb +36 -10
- data/lib/reform/form/call.rb +1 -1
- data/lib/reform/form/composition.rb +2 -2
- data/lib/reform/form/dry.rb +10 -58
- data/lib/reform/form/dry/input_hash.rb +37 -0
- data/lib/reform/form/dry/new_api.rb +45 -0
- data/lib/reform/form/dry/old_api.rb +61 -0
- data/lib/reform/form/populator.rb +11 -27
- data/lib/reform/form/prepopulate.rb +4 -3
- data/lib/reform/form/validate.rb +28 -13
- data/lib/reform/result.rb +90 -0
- data/lib/reform/validation.rb +19 -11
- data/lib/reform/validation/groups.rb +12 -27
- data/lib/reform/version.rb +1 -1
- data/reform.gemspec +14 -13
- data/test/benchmarking.rb +39 -6
- data/test/call_new_api.rb +23 -0
- data/test/call_old_api.rb +23 -0
- data/test/changed_test.rb +14 -14
- data/test/coercion_test.rb +57 -25
- data/test/composition_new_api.rb +186 -0
- data/test/composition_old_api.rb +184 -0
- data/test/contract/custom_error_test.rb +55 -0
- data/test/contract_new_api.rb +77 -0
- data/test/contract_old_api.rb +77 -0
- data/test/default_test.rb +4 -4
- data/test/deserialize_test.rb +17 -20
- data/test/errors_new_api.rb +225 -0
- data/test/errors_old_api.rb +230 -0
- data/test/feature_test.rb +10 -12
- data/test/fixtures/dry_error_messages.yml +73 -23
- data/test/fixtures/dry_new_api_error_messages.yml +104 -0
- data/test/form_new_api.rb +57 -0
- data/test/{form_test.rb → form_old_api.rb} +8 -8
- data/test/form_option_new_api.rb +24 -0
- data/test/{form_option_test.rb → form_option_old_api.rb} +5 -5
- data/test/from_test.rb +18 -22
- data/test/inherit_new_api.rb +105 -0
- data/test/inherit_old_api.rb +105 -0
- data/test/{module_test.rb → module_new_api.rb} +26 -31
- data/test/module_old_api.rb +146 -0
- data/test/parse_option_test.rb +40 -0
- data/test/parse_pipeline_test.rb +4 -4
- data/test/populate_new_api.rb +304 -0
- data/test/populate_old_api.rb +304 -0
- data/test/populator_skip_test.rb +11 -11
- data/test/prepopulator_test.rb +23 -24
- data/test/read_only_test.rb +12 -1
- data/test/readable_test.rb +9 -9
- data/test/reform_new_api.rb +204 -0
- data/test/{reform_test.rb → reform_old_api.rb} +44 -65
- data/test/save_new_api.rb +101 -0
- data/test/save_old_api.rb +101 -0
- data/test/setup_test.rb +17 -17
- data/test/skip_if_new_api.rb +85 -0
- data/test/skip_if_old_api.rb +92 -0
- data/test/skip_setter_and_getter_test.rb +9 -10
- data/test/test_helper.rb +25 -14
- data/test/validate_new_api.rb +453 -0
- data/test/{validate_test.rb → validate_old_api.rb} +121 -131
- data/test/validation/dry_validation_new_api.rb +835 -0
- data/test/validation/dry_validation_old_api.rb +772 -0
- data/test/validation/result_test.rb +77 -0
- data/test/validation_library_provided_test.rb +16 -0
- data/test/virtual_test.rb +47 -7
- data/test/writeable_test.rb +38 -9
- metadata +111 -56
- data/gemfiles/Gemfile.disposable-0.3 +0 -6
- data/lib/reform/contract/errors.rb +0 -43
- data/lib/reform/form/mongoid.rb +0 -37
- data/lib/reform/form/orm.rb +0 -26
- data/lib/reform/mongoid.rb +0 -4
- data/test/call_test.rb +0 -23
- data/test/composition_test.rb +0 -149
- data/test/contract_test.rb +0 -77
- data/test/deprecation_test.rb +0 -27
- data/test/errors_test.rb +0 -165
- data/test/inherit_test.rb +0 -119
- data/test/populate_test.rb +0 -270
- data/test/readonly_test.rb +0 -14
- data/test/save_test.rb +0 -89
- data/test/skip_if_test.rb +0 -74
- data/test/validation/dry_test.rb +0 -60
- data/test/validation/dry_validation_test.rb +0 -352
- data/test/validation/errors.yml +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 0f5d5dea8c04f5d993a91776afffea2a0b48603d850c11204d04e79248be6cf8
|
4
|
+
data.tar.gz: e4132e9db35384198bf31797b8620219c6418df4781a8f5300bbcf38c1a1c630
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '0845ada0bbafc7c3a45485d51f93c66c8616bee7b23c851712d297be20c73e82f23a8e575f803adb2972c382c4c9003951ae8d788fe12df87195950490505028'
|
7
|
+
data.tar.gz: bd463ddb326f4db34ef9ad6948cdb9466a56c87514f2a18fcafba6dff29b54baf5640b97b490657b92e438c336869f35adc3e407b91be80351f427fd84f28c35
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -1,11 +1,16 @@
|
|
1
1
|
language: ruby
|
2
|
+
cache: bundler
|
3
|
+
bundler_args: --without benchmarks tools
|
2
4
|
rvm:
|
3
|
-
-
|
4
|
-
- 2.
|
5
|
+
- ruby-head
|
6
|
+
- 2.7
|
7
|
+
- 2.6
|
8
|
+
- 2.5
|
9
|
+
- 2.4
|
5
10
|
gemfile:
|
6
|
-
- gemfiles/
|
7
|
-
|
11
|
+
- gemfiles/1.5.0.gemfile
|
12
|
+
- gemfiles/0.13.0.gemfile
|
8
13
|
matrix:
|
9
14
|
fast_finish: true
|
10
|
-
|
11
|
-
|
15
|
+
allow_failures:
|
16
|
+
- rvm: ruby-head
|
data/Appraisals
ADDED
data/CHANGES.md
CHANGED
@@ -1,9 +1,62 @@
|
|
1
|
+
## 2.3.3
|
2
|
+
|
3
|
+
* Rename validation option for dry-v 1+ to `contract` instead of `schema`
|
4
|
+
|
5
|
+
## 2.3.2
|
6
|
+
|
7
|
+
* Fix Validation block option :form incorrectly memoized between tests
|
8
|
+
|
9
|
+
## 2.3.1
|
10
|
+
* With dry-validation 1.5 the form is always injected. Just add option :form to access it in the schema.
|
11
|
+
* Removed global monkey patching of Dry::Schema::DSL
|
12
|
+
* Tests in ruby 2.7
|
13
|
+
|
14
|
+
## 2.3.0
|
15
|
+
|
16
|
+
You can upgrade from 2.2.0 without worries.
|
17
|
+
|
18
|
+
* Require Representable 3.0.0 and **removed Representable 2.4 deprecation code**.
|
19
|
+
* Require Disposable 0.4.0 which fixes issues with `nil` field values, `sync {}` and dry-validation.
|
20
|
+
* Fix boolean coercion.
|
21
|
+
* Allow using `:populator` classes marked with `Uber::Callable`.
|
22
|
+
* Introduce `parse: false` as a shortcut for `deserialzer: { writeable: false}`. Thanks to @pabloh for insisting on this handy change.
|
23
|
+
* Memoize the deserializer instance on the class level via `::deserializer`. This saves the inferal of a deserializing representer and speeds up following calls by 130%.
|
24
|
+
* Deprecated positional arguments for `validation :default, options: {}`. New API: `validation name: :default, **`.
|
25
|
+
* Reform now maintains a generic `Dry::Schema` class for global schema configuration. Can be overridden via `::validation`.
|
26
|
+
* When validating with dry-validation, we now pass a symbolized hash. We also replaced `Dry::Validation::Form` with `Schema` which won't coerce values where it shouldn't.
|
27
|
+
* [private] `Group#call` API now is: `call(form, errors)`.
|
28
|
+
* Modify `Form#valid?` - simply calls `validate({})`.
|
29
|
+
* In `:if` for validation groups, you now get a hash of result objects, not just true/false.
|
30
|
+
* Allow adding a custom error AFTER validate has been already called
|
31
|
+
|
32
|
+
Compatibility with `dry-validation` with 1.x:
|
33
|
+
* [CHANGE] seems like "custom" predicate are not supported by `dry-schema` anymore or better the same result is reached using the `rule` method:
|
34
|
+
Something like this:
|
35
|
+
```ruby
|
36
|
+
validation do
|
37
|
+
def a_song?(value)
|
38
|
+
value == :really_cool_song
|
39
|
+
end
|
40
|
+
|
41
|
+
required(:songs).filled(:a_song?)
|
42
|
+
end
|
43
|
+
```
|
44
|
+
will be something like:
|
45
|
+
```ruby
|
46
|
+
validation do
|
47
|
+
required(:songs).filled
|
48
|
+
|
49
|
+
rule(:songs) do
|
50
|
+
key.failure(:a_song?) unless value == :really_cool_song
|
51
|
+
end
|
52
|
+
end
|
53
|
+
```
|
54
|
+
* [BREAKING] inheriting/merging/overriding schema/rules is not supported by `dry-v` so the `inherit:` option is **NOT SUPPORTED** for now. Also extend a `schema:` option using a block is **NOT SUPPORTED** for now. Possible workaround is to use reform module to compose different validations but this won't override existing validations but just merge them
|
55
|
+
|
1
56
|
## 2.2.4
|
2
57
|
|
3
|
-
*
|
4
|
-
|
5
|
-
The only difference here is that `Form#sync`/`#save` with a block will include `nil` properties into the nested hash.
|
6
|
-
* Remove `uber` dependency.
|
58
|
+
* You can now use any object with `call` as a populator, no need to `include Uber::Callable` anymore. This is because we have only three types and don't need a `is_a?` or `respond_to?` check.
|
59
|
+
* Use `declarative-option` and loosen `uber` dependency.
|
7
60
|
|
8
61
|
## 2.2.3
|
9
62
|
|
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
## How to contribute to Reform
|
2
|
+
|
3
|
+
#### **Did you find a bug?**
|
4
|
+
|
5
|
+
* **Ensure the bug was not already reported** by searching on GitHub under [Issues](https://github.com/trailblazer/reform/issues).
|
6
|
+
|
7
|
+
* If you're unable to find an open issue addressing the problem, [open a new one](https://github.com/trailblazer/reform/issues/new). Be sure to follow the issue template.
|
8
|
+
|
9
|
+
#### **Did you write a patch that fixes a bug?**
|
10
|
+
|
11
|
+
* Open a new GitHub pull request with the patch.
|
12
|
+
|
13
|
+
* Ensure the PR description clearly describes the problem and solution. Include the relevant issue number if applicable.
|
14
|
+
|
15
|
+
* All code in pull requests is assumed to be MIT licensed. Do not submit a pull request if that isn't the case.
|
16
|
+
|
17
|
+
#### **Do you intend to add a new feature or change an existing one?**
|
18
|
+
|
19
|
+
* Suggest your change in the [Trailblazer Gitter Room](https://gitter.im/trailblazer/chat) and start writing code.
|
20
|
+
|
21
|
+
* Do not open an issue on GitHub until you have collected positive feedback about the change. GitHub issues are primarily intended for bug reports and fixes.
|
22
|
+
|
23
|
+
#### **Do you have questions using Reform?**
|
24
|
+
|
25
|
+
* Ask any questions about how to use Reform in the [Trailblazer Gitter Room](https://gitter.im/trailblazer/chat). Github issues are restricted to bug reports and fixes.
|
26
|
+
|
27
|
+
* GitHub Issues should not be used as a help forum and any such issues will be closed.
|
28
|
+
|
29
|
+
#### **Do you want to contribute to the Reform documentation?**
|
30
|
+
|
31
|
+
* Reform documentation is provided via the [Trailblazer site](http://trailblazer.to/gems/reform/) and not the repository readme. Please add your contributions to the [Trailblazer site repository](https://github.com/trailblazer/trailblazer.github.io)
|
data/Gemfile
CHANGED
@@ -1,19 +1,5 @@
|
|
1
|
-
source
|
1
|
+
source "https://rubygems.org"
|
2
2
|
|
3
3
|
gemspec
|
4
4
|
|
5
|
-
|
6
|
-
# gem "representable", "2.4.0.rc5"
|
7
|
-
# gem 'representable', path: "../representable"
|
8
|
-
# # gem 'representable', github: "apotonick/representable"
|
9
|
-
# gem "disposable", path: "../disposable"
|
10
|
-
# gem "disposable", github: "apotonick/disposable"
|
11
|
-
|
12
|
-
|
13
|
-
# gem "declarative", path: "../declarative"
|
14
|
-
|
15
|
-
gem "minitest-line"
|
16
|
-
gem 'byebug'
|
17
|
-
|
18
|
-
# gem "uber", path: "../uber"
|
19
|
-
gem "representable", ">= 3.0.1"
|
5
|
+
gem "appraisal", "~> 2.2"
|
data/ISSUE_TEMPLATE.md
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
Note: If you have a question about Reform, would like help using
|
2
|
+
Reform, want to request a feature, or do anything else other than
|
3
|
+
submit a bug report, please use the [Trailblazer gitter channel](https://gitter.im/trailblazer/chat).
|
4
|
+
|
5
|
+
Note: Rails/ ActiveRecord/ ActiveModel support.
|
6
|
+
As of Reform 2.2.0 all Rails/ Active-* code was moved to the [reform-rails](https://github.com/trailblazer/reform-rails) gem.
|
7
|
+
Make sure you are contributing to the correct gem!
|
8
|
+
|
9
|
+
### Complete Description of Issue
|
10
|
+
|
11
|
+
|
12
|
+
### Steps to reproduce
|
13
|
+
|
14
|
+
|
15
|
+
### Expected behavior
|
16
|
+
Tell us what should happen
|
17
|
+
|
18
|
+
### Actual behavior
|
19
|
+
Tell us what happens instead
|
20
|
+
|
21
|
+
### System configuration
|
22
|
+
**Reform version**:
|
23
|
+
|
24
|
+
### Full Backtrace of Exception (if any)
|
25
|
+
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
[![Gitter Chat](https://badges.gitter.im/trailblazer/chat.svg)](https://gitter.im/trailblazer/chat)
|
4
4
|
[![TRB Newsletter](https://img.shields.io/badge/TRB-newsletter-lightgrey.svg)](http://trailblazer.to/newsletter/)
|
5
5
|
[![Build
|
6
|
-
Status](https://travis-ci.org/
|
6
|
+
Status](https://travis-ci.org/trailblazer/reform.svg)](https://travis-ci.org/trailblazer/reform)
|
7
7
|
[![Gem Version](https://badge.fury.io/rb/reform.svg)](http://badge.fury.io/rb/reform)
|
8
8
|
|
9
9
|
_Form objects decoupled from your models._
|
@@ -296,7 +296,7 @@ Put this in an initializer or on top of your script.
|
|
296
296
|
Reform allows to map multiple models to one form. The [complete documentation](https://github.com/apotonick/disposable#composition) is here, however, this is how it works.
|
297
297
|
|
298
298
|
```ruby
|
299
|
-
class
|
299
|
+
class AlbumForm < Reform::Form
|
300
300
|
include Composition
|
301
301
|
|
302
302
|
property :id, on: :album
|
@@ -315,20 +315,18 @@ AlbumForm.new(album: album, cd: CD.find(1))
|
|
315
315
|
|
316
316
|
Reform comes many more optional features, like hash fields, coercion, virtual fields, and so on. Check the [full documentation here](http://trailblazer.to/gems/reform).
|
317
317
|
|
318
|
-
|
319
|
-
![](http://trailblazer.to/images/3dbuch-freigestellt.png)
|
320
|
-
</a>
|
318
|
+
[![](http://trailblazer.to/images/3dbuch-freigestellt.png)](https://leanpub.com/trailblazer)
|
321
319
|
|
322
320
|
Reform is part of the [Trailblazer project](http://trailblazer.to). Please [buy my book](https://leanpub.com/trailblazer) to support the development and learn everything about Reform - there's two chapters dedicated to Reform!
|
323
321
|
|
324
322
|
|
325
323
|
## Security And Strong_parameters
|
326
324
|
|
327
|
-
By
|
325
|
+
By explicitly defining the form layout using `::property` there is no more need for protecting from unwanted input. `strong_parameter` or `attr_accessible` become obsolete. Reform will simply ignore undefined incoming parameters.
|
328
326
|
|
329
327
|
## This is not Reform 1.x!
|
330
328
|
|
331
|
-
Temporary note: This is the README and API for Reform 2. On the public API, only a few tiny things have changed. Here are the [Reform 1.2 docs](https://github.com/
|
329
|
+
Temporary note: This is the README and API for Reform 2. On the public API, only a few tiny things have changed. Here are the [Reform 1.2 docs](https://github.com/trailblazer/reform/blob/v1.2.6/README.md).
|
332
330
|
|
333
331
|
Anyway, please upgrade and _report problems_ and do not simply assume that we will magically find out what needs to get fixed. When in trouble, join us on [Gitter](https://gitter.im/trailblazer/chat).
|
334
332
|
|
data/Rakefile
CHANGED
@@ -1,15 +1,22 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
|
-
require
|
2
|
+
require "rake/testtask"
|
3
|
+
require "dry/types/version"
|
3
4
|
|
4
|
-
task :
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
task default: %i[test]
|
6
|
+
|
7
|
+
TEST_WITH_OLD_AND_NEW_API = %w[
|
8
|
+
validation/dry_validation call composition contract errors inherit module reform
|
9
|
+
save skip_if populate validate form
|
10
|
+
].freeze
|
11
|
+
|
12
|
+
def dry_v_test_files
|
13
|
+
api = Gem::Version.new(Dry::Types::VERSION).to_s.split('.').first.to_i >= 1 ? "new" : "old"
|
14
|
+
TEST_WITH_OLD_AND_NEW_API.map { |file| "test/#{file}_#{api}_api.rb" }
|
9
15
|
end
|
10
16
|
|
11
|
-
Rake::TestTask.new(:
|
12
|
-
test.libs <<
|
13
|
-
test.test_files = FileList[
|
17
|
+
Rake::TestTask.new(:test) do |test|
|
18
|
+
test.libs << "test"
|
19
|
+
test.test_files = FileList["test/*_test.rb"] + FileList["test/validation/*_test.rb"] + dry_v_test_files
|
14
20
|
test.verbose = true
|
15
21
|
end
|
22
|
+
|
data/lib/reform.rb
CHANGED
data/lib/reform/contract.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
|
-
require "uber/inheritable_attr"
|
2
|
-
|
3
1
|
module Reform
|
4
2
|
# Define your form structure and its validations. Instantiate it with a model,
|
5
3
|
# and then +validate+ this object graph.
|
6
4
|
class Contract < Disposable::Twin
|
5
|
+
require "reform/contract/custom_error"
|
7
6
|
require "disposable/twin/composition" # Expose.
|
8
7
|
include Expose
|
9
8
|
|
@@ -15,7 +14,7 @@ module Reform
|
|
15
14
|
Contract
|
16
15
|
end
|
17
16
|
|
18
|
-
def self.property(name, options={}, &block)
|
17
|
+
def self.property(name, options = {}, &block)
|
19
18
|
if twin = options.delete(:form)
|
20
19
|
options[:twin] = twin
|
21
20
|
end
|
@@ -27,14 +26,13 @@ module Reform
|
|
27
26
|
super
|
28
27
|
end
|
29
28
|
|
30
|
-
# FIXME: test me.
|
31
29
|
def self.properties(*args)
|
32
30
|
options = args.last.is_a?(Hash) ? args.pop : {}
|
33
31
|
args.each { |name| property(name, options.dup) }
|
34
32
|
end
|
35
33
|
|
36
|
-
require "reform/
|
37
|
-
require
|
34
|
+
require "reform/result"
|
35
|
+
require "reform/contract/validate"
|
38
36
|
include Reform::Contract::Validate
|
39
37
|
|
40
38
|
require "reform/validation"
|
@@ -44,23 +42,16 @@ module Reform
|
|
44
42
|
require "disposable/twin/sync"
|
45
43
|
include Disposable::Twin::Sync
|
46
44
|
|
45
|
+
private
|
47
46
|
|
48
|
-
|
49
|
-
# module ValidatesWarning
|
50
|
-
# def validates(*)
|
51
|
-
# raise "[Reform] Please include either Reform::Form::ActiveModel::Validations or Reform::Form::Lotus in your form class."
|
52
|
-
# end
|
53
|
-
# end
|
54
|
-
# extend ValidatesWarning
|
55
|
-
|
56
|
-
private
|
57
47
|
# DISCUSS: separate file?
|
58
48
|
module Readonly
|
59
49
|
def readonly?(name)
|
60
50
|
options_for(name)[:writeable] == false
|
61
51
|
end
|
52
|
+
|
62
53
|
def options_for(name)
|
63
|
-
|
54
|
+
self.class.options_for(name)
|
64
55
|
end
|
65
56
|
end
|
66
57
|
|
@@ -69,7 +60,6 @@ module Reform
|
|
69
60
|
end
|
70
61
|
include Readonly
|
71
62
|
|
72
|
-
|
73
63
|
def self.clone # TODO: test. THIS IS ONLY FOR Trailblazer when contract gets cloned in suboperation.
|
74
64
|
Class.new(self)
|
75
65
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Reform
|
2
|
+
class Contract < Disposable::Twin
|
3
|
+
# a "fake" Dry schema object to add into the @results array
|
4
|
+
# super ugly hack required for 2.3.x version since we are creating
|
5
|
+
# a new Reform::Errors instance every time we call form.errors
|
6
|
+
class CustomError
|
7
|
+
def initialize(key, error_text, results)
|
8
|
+
@key = key
|
9
|
+
@error_text = error_text
|
10
|
+
@errors = {key => Array(error_text)}
|
11
|
+
@messages = @errors
|
12
|
+
@hint = {}
|
13
|
+
@results = results
|
14
|
+
|
15
|
+
merge!
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_reader :messages, :hint
|
19
|
+
|
20
|
+
def success?
|
21
|
+
false
|
22
|
+
end
|
23
|
+
|
24
|
+
def failure?
|
25
|
+
true
|
26
|
+
end
|
27
|
+
|
28
|
+
# dry 1.x errors method has 1 kwargs argument
|
29
|
+
def errors(**_args)
|
30
|
+
@errors
|
31
|
+
end
|
32
|
+
|
33
|
+
def merge!
|
34
|
+
# to_h required for dry_v 1.x since the errors are Dry object instead of an hash
|
35
|
+
@results.map(&:errors)
|
36
|
+
.detect { |hash| hash.to_h.key?(@key) }
|
37
|
+
.tap { |hash| hash.nil? ? @results << self : hash.to_h[@key] |= Array(@error_text) }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -1,33 +1,63 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
class Reform::Contract < Disposable::Twin
|
2
|
+
module Validate
|
3
|
+
def initialize(*)
|
4
|
+
# this will be removed in Reform 3.0. we need this for the presenting form, form builders
|
5
|
+
# call the Form#errors method before validation.
|
6
|
+
super
|
7
|
+
@result = Result.new([])
|
8
|
+
end
|
6
9
|
|
7
|
-
|
10
|
+
def validate
|
11
|
+
validate!(nil).success?
|
12
|
+
end
|
8
13
|
|
9
|
-
|
10
|
-
|
14
|
+
# The #errors method will be removed in Reform 2.4/3.0 core.
|
15
|
+
def errors(*args)
|
16
|
+
Result::Errors.new(@result, self)
|
17
|
+
end
|
11
18
|
|
12
|
-
|
13
|
-
|
19
|
+
#:private:
|
20
|
+
# only used in tests so far. this will be the new API in #call, where you will get @result.
|
21
|
+
def to_result
|
22
|
+
@result
|
23
|
+
end
|
24
|
+
|
25
|
+
def custom_errors
|
26
|
+
@result.to_results.select { |result| result.is_a? Reform::Contract::CustomError }
|
27
|
+
end
|
14
28
|
|
15
|
-
|
16
|
-
|
29
|
+
def validate!(name, pointers = [])
|
30
|
+
# run local validations. this could be nested schemas, too.
|
31
|
+
local_errors_by_group = Reform::Validation::Groups::Validate.(self.class.validation_groups, self).compact # TODO: discss compact
|
17
32
|
|
18
|
-
|
33
|
+
# blindly add injected pointers. will be readable via #errors.
|
34
|
+
# also, add pointers from local errors here.
|
35
|
+
pointers_for_nested = pointers + local_errors_by_group.collect { |errs| Result::Pointer.new(errs, []) }.compact
|
19
36
|
|
20
|
-
|
21
|
-
|
22
|
-
|
37
|
+
nested_errors = validate_nested!(pointers_for_nested)
|
38
|
+
|
39
|
+
# Result: unified interface #success?, #messages, etc.
|
40
|
+
@result = Result.new(custom_errors + local_errors_by_group + pointers, nested_errors)
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
# Recursively call validate! on nested forms.
|
46
|
+
# A pointer keeps an entire result object (e.g. Dry result) and
|
47
|
+
# the relevant path to its fragment, e.g. <Dry::result{.....} path=songs,0>
|
48
|
+
def validate_nested!(pointers)
|
49
|
+
arr = []
|
50
|
+
|
51
|
+
schema.each(twin: true) do |dfn|
|
52
|
+
# on collections, this calls validate! on each item form.
|
53
|
+
Disposable::Twin::PropertyProcessor.new(dfn, self).() do |form, i|
|
54
|
+
nested_pointers = pointers.collect { |pointer| pointer.advance(dfn[:name].to_sym, i) }.compact # pointer contains fragment for us, so go deeper
|
23
55
|
|
24
|
-
|
56
|
+
arr << form.validate!(dfn[:name], nested_pointers)
|
57
|
+
end
|
58
|
+
end
|
25
59
|
|
26
|
-
|
27
|
-
def validate_nested!(errors, prefixes)
|
28
|
-
schema.each(twin: true) do |dfn|
|
29
|
-
# recursively call valid? on nested form.
|
30
|
-
Disposable::Twin::PropertyProcessor.new(dfn, self).() { |form| form.validate!(errors, prefixes+[dfn[:name]]) }
|
60
|
+
arr
|
31
61
|
end
|
32
62
|
end
|
33
|
-
end
|
63
|
+
end
|