reform 2.3.0.rc1 → 2.5.0
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 +5 -5
- data/.gitignore +5 -1
- data/.travis.yml +7 -11
- data/CHANGES.md +43 -3
- data/Gemfile +2 -5
- data/ISSUE_TEMPLATE.md +1 -1
- data/LICENSE.txt +1 -1
- data/README.md +7 -9
- data/Rakefile +6 -10
- data/lib/reform/contract.rb +7 -7
- data/lib/reform/contract/custom_error.rb +41 -0
- data/lib/reform/contract/validate.rb +10 -6
- data/lib/reform/errors.rb +27 -15
- data/lib/reform/form.rb +22 -11
- data/lib/reform/form/call.rb +1 -1
- data/lib/reform/form/composition.rb +2 -2
- data/lib/reform/form/dry.rb +22 -60
- data/lib/reform/form/dry/input_hash.rb +37 -0
- data/lib/reform/form/populator.rb +9 -11
- data/lib/reform/form/prepopulate.rb +3 -2
- data/lib/reform/form/validate.rb +19 -12
- data/lib/reform/result.rb +36 -9
- data/lib/reform/validation.rb +10 -8
- data/lib/reform/validation/groups.rb +2 -4
- data/lib/reform/version.rb +1 -1
- data/reform.gemspec +9 -9
- data/test/benchmarking.rb +10 -11
- data/test/call_test.rb +8 -8
- data/test/changed_test.rb +13 -13
- data/test/coercion_test.rb +56 -24
- data/test/composition_test.rb +49 -51
- data/test/contract/custom_error_test.rb +55 -0
- data/test/contract_test.rb +18 -18
- data/test/default_test.rb +3 -3
- data/test/deserialize_test.rb +14 -17
- data/test/docs/validation_test.rb +134 -0
- data/test/errors_test.rb +131 -86
- data/test/feature_test.rb +9 -11
- data/test/fixtures/dry_error_messages.yml +65 -52
- data/test/form_option_test.rb +3 -3
- data/test/form_test.rb +6 -6
- data/test/from_test.rb +17 -21
- data/test/inherit_test.rb +28 -35
- data/test/module_test.rb +23 -28
- data/test/parse_option_test.rb +12 -12
- data/test/parse_pipeline_test.rb +3 -3
- data/test/populate_test.rb +146 -93
- data/test/populator_skip_test.rb +3 -4
- data/test/prepopulator_test.rb +20 -21
- data/test/read_only_test.rb +12 -1
- data/test/readable_test.rb +7 -7
- data/test/reform_test.rb +38 -42
- data/test/save_test.rb +16 -19
- data/test/setup_test.rb +15 -15
- data/test/skip_if_test.rb +30 -19
- data/test/skip_setter_and_getter_test.rb +8 -9
- data/test/test_helper.rb +12 -5
- data/test/validate_test.rb +160 -140
- data/test/validation/dry_validation_test.rb +407 -236
- data/test/validation/result_test.rb +29 -31
- data/test/validation_library_provided_test.rb +3 -3
- data/test/virtual_test.rb +46 -6
- data/test/writeable_test.rb +13 -13
- metadata +32 -29
- data/test/readonly_test.rb +0 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e0b6b3c1dbb48304ae8b36f5fbc12d9f7149edc61b40757017472b3eb01cf04f
|
4
|
+
data.tar.gz: 689811ffa73a062d4e598d8a36b6258571350d1ce4c5c87c85db9707313dde04
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a797c79e164c4c1791661a97163d4e89b1b2e49ae4992e1c0a59eb427d98ddfdbdae96292f455f843acacc869b5053916afa7131018843c66f4d886e6872c372
|
7
|
+
data.tar.gz: 82fe647e1ab34dcc24e85250d5876b88b84ea3a991cdfb163bf0dd616be701105ab1ca87065285bc0e32abe9f67ccdb3cda103c7f70143e49d0a8c3024baa75e
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -2,16 +2,12 @@ language: ruby
|
|
2
2
|
cache: bundler
|
3
3
|
bundler_args: --without benchmarks tools
|
4
4
|
rvm:
|
5
|
-
-
|
6
|
-
- 2.
|
7
|
-
- 2.
|
8
|
-
- 2.
|
5
|
+
- ruby-head
|
6
|
+
- 2.7
|
7
|
+
- 2.6
|
8
|
+
- 2.5
|
9
|
+
- 2.4
|
9
10
|
matrix:
|
10
11
|
fast_finish: true
|
11
|
-
|
12
|
-
|
13
|
-
urls:
|
14
|
-
- https://webhooks.gitter.im/e/680e86d98056f2ae2fd7
|
15
|
-
on_success: change # options: [always|never|change] default: always
|
16
|
-
on_failure: always # options: [always|never|change] default: always
|
17
|
-
on_start: never # options: [always|never|change] default: always
|
12
|
+
allow_failures:
|
13
|
+
- rvm: ruby-head
|
data/CHANGES.md
CHANGED
@@ -1,8 +1,25 @@
|
|
1
|
-
##
|
1
|
+
## 2.5.0
|
2
|
+
* fix memory leak with Dry validation (#525)
|
2
3
|
|
4
|
+
## 2.4.0
|
5
|
+
|
6
|
+
* [BREAKING] Dropping compatibility of dry-validation < 1.x
|
3
7
|
[* Removed `Reform::Contract` ?]
|
4
8
|
[* Move Form#deserializer to Form::deserializer]
|
5
9
|
|
10
|
+
## 2.3.3
|
11
|
+
|
12
|
+
* Rename validation option for dry-v 1+ to `contract` instead of `schema`
|
13
|
+
|
14
|
+
## 2.3.2
|
15
|
+
|
16
|
+
* Fix Validation block option :form incorrectly memoized between tests
|
17
|
+
|
18
|
+
## 2.3.1
|
19
|
+
* With dry-validation 1.5 the form is always injected. Just add option :form to access it in the schema.
|
20
|
+
* Removed global monkey patching of Dry::Schema::DSL
|
21
|
+
* Tests in ruby 2.7
|
22
|
+
|
6
23
|
## 2.3.0
|
7
24
|
|
8
25
|
You can upgrade from 2.2.0 without worries.
|
@@ -17,10 +34,33 @@ You can upgrade from 2.2.0 without worries.
|
|
17
34
|
* Reform now maintains a generic `Dry::Schema` class for global schema configuration. Can be overridden via `::validation`.
|
18
35
|
* 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.
|
19
36
|
* [private] `Group#call` API now is: `call(form, errors)`.
|
20
|
-
*
|
21
|
-
|
37
|
+
* Modify `Form#valid?` - simply calls `validate({})`.
|
22
38
|
* In `:if` for validation groups, you now get a hash of result objects, not just true/false.
|
39
|
+
* Allow adding a custom error AFTER validate has been already called
|
40
|
+
|
41
|
+
Compatibility with `dry-validation` with 1.x:
|
42
|
+
* [CHANGE] seems like "custom" predicate are not supported by `dry-schema` anymore or better the same result is reached using the `rule` method:
|
43
|
+
Something like this:
|
44
|
+
```ruby
|
45
|
+
validation do
|
46
|
+
def a_song?(value)
|
47
|
+
value == :really_cool_song
|
48
|
+
end
|
23
49
|
|
50
|
+
required(:songs).filled(:a_song?)
|
51
|
+
end
|
52
|
+
```
|
53
|
+
will be something like:
|
54
|
+
```ruby
|
55
|
+
validation do
|
56
|
+
required(:songs).filled
|
57
|
+
|
58
|
+
rule(:songs) do
|
59
|
+
key.failure(:a_song?) unless value == :really_cool_song
|
60
|
+
end
|
61
|
+
end
|
62
|
+
```
|
63
|
+
* [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
|
24
64
|
|
25
65
|
## 2.2.4
|
26
66
|
|
data/Gemfile
CHANGED
data/ISSUE_TEMPLATE.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Note: If you have a question about Reform, would like help using
|
2
2
|
Reform, want to request a feature, or do anything else other than
|
3
|
-
submit a bug report, please use the Trailblazer gitter channel.
|
3
|
+
submit a bug report, please use the [Trailblazer gitter channel](https://gitter.im/trailblazer/chat).
|
4
4
|
|
5
5
|
Note: Rails/ ActiveRecord/ ActiveModel support.
|
6
6
|
As of Reform 2.2.0 all Rails/ Active-* code was moved to the [reform-rails](https://github.com/trailblazer/reform-rails) gem.
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -10,11 +10,11 @@ _Form objects decoupled from your models._
|
|
10
10
|
|
11
11
|
Reform gives you a form object with validations and nested setup of models. It is completely framework-agnostic and doesn't care about your database.
|
12
12
|
|
13
|
-
Although reform can be used in any Ruby framework, it comes with [Rails support](#rails-integration), works with
|
13
|
+
Although reform can be used in any Ruby framework, it comes with [Rails support](#rails-integration), works with simple_form and other form gems, allows nesting forms to implement has_one and has_many relationships, can [compose a form](#compositions) from multiple objects and gives you coercion.
|
14
14
|
|
15
15
|
## Full Documentation
|
16
16
|
|
17
|
-
Reform is part of the [Trailblazer](http://trailblazer.to) framework. [Full documentation](http://trailblazer.to/
|
17
|
+
Reform is part of the [Trailblazer](http://trailblazer.to) framework. [Full documentation](http://trailblazer.to/2.1/docs/reform.html) is available on the project site.
|
18
18
|
|
19
19
|
## Reform 2.2
|
20
20
|
|
@@ -250,7 +250,7 @@ The manual saving with block is not encouraged. You should rather check the Disp
|
|
250
250
|
|
251
251
|
## Populating Forms
|
252
252
|
|
253
|
-
Very often, you need to give Reform some information how to create or find nested objects when `validate`ing. This directive is called _populator_ and [documented here](http://trailblazer.to/
|
253
|
+
Very often, you need to give Reform some information how to create or find nested objects when `validate`ing. This directive is called _populator_ and [documented here](http://trailblazer.to/2.1/docs/reform.html#reform-populators).
|
254
254
|
|
255
255
|
## Installation
|
256
256
|
|
@@ -313,18 +313,16 @@ AlbumForm.new(album: album, cd: CD.find(1))
|
|
313
313
|
|
314
314
|
## More
|
315
315
|
|
316
|
-
Reform comes many more optional features, like hash fields, coercion, virtual fields, and so on. Check the [full documentation here](http://trailblazer.to/
|
316
|
+
Reform comes many more optional features, like hash fields, coercion, virtual fields, and so on. Check the [full documentation here](http://trailblazer.to/2.1/docs/reform.html).
|
317
317
|
|
318
|
-
|
319
|
-

|
320
|
-
</a>
|
318
|
+
[](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
|
|
@@ -332,7 +330,7 @@ Temporary note: This is the README and API for Reform 2. On the public API, only
|
|
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
|
|
335
|
-
[Full documentation for Reform](http://trailblazer.to/
|
333
|
+
[Full documentation for Reform](http://trailblazer.to/2.1/docs/reform.html) is available online, or support us and grab the [Trailblazer book](https://leanpub.com/trailblazer). There is an [Upgrading Guide](http://trailblazer.to/2.1/docs/reform.html#reform-upgrading-guide) to help you migrate through versions.
|
336
334
|
|
337
335
|
### Attributions!!!
|
338
336
|
|
data/Rakefile
CHANGED
@@ -1,15 +1,11 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
|
-
require
|
2
|
+
require "rake/testtask"
|
3
|
+
require "dry/types/version"
|
3
4
|
|
4
|
-
task :
|
5
|
-
Rake::TestTask.new(:test) do |test|
|
6
|
-
test.libs << 'test'
|
7
|
-
test.test_files = FileList['test/*_test.rb'] + FileList["test/validation/*_test.rb"]
|
8
|
-
test.verbose = true
|
9
|
-
end
|
5
|
+
task default: %i[test]
|
10
6
|
|
11
|
-
Rake::TestTask.new(:
|
12
|
-
test.libs <<
|
13
|
-
test.test_files = FileList[
|
7
|
+
Rake::TestTask.new(:test) do |test|
|
8
|
+
test.libs << "test"
|
9
|
+
test.test_files = FileList["test/**/*_test.rb"]
|
14
10
|
test.verbose = true
|
15
11
|
end
|
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
|
@@ -33,7 +32,7 @@ module Reform
|
|
33
32
|
end
|
34
33
|
|
35
34
|
require "reform/result"
|
36
|
-
require
|
35
|
+
require "reform/contract/validate"
|
37
36
|
include Reform::Contract::Validate
|
38
37
|
|
39
38
|
require "reform/validation"
|
@@ -43,14 +42,16 @@ module Reform
|
|
43
42
|
require "disposable/twin/sync"
|
44
43
|
include Disposable::Twin::Sync
|
45
44
|
|
46
|
-
|
45
|
+
private
|
46
|
+
|
47
47
|
# DISCUSS: separate file?
|
48
48
|
module Readonly
|
49
49
|
def readonly?(name)
|
50
50
|
options_for(name)[:writeable] == false
|
51
51
|
end
|
52
|
+
|
52
53
|
def options_for(name)
|
53
|
-
|
54
|
+
self.class.options_for(name)
|
54
55
|
end
|
55
56
|
end
|
56
57
|
|
@@ -59,7 +60,6 @@ module Reform
|
|
59
60
|
end
|
60
61
|
include Readonly
|
61
62
|
|
62
|
-
|
63
63
|
def self.clone # TODO: test. THIS IS ONLY FOR Trailblazer when contract gets cloned in suboperation.
|
64
64
|
Class.new(self)
|
65
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
|
@@ -11,7 +11,7 @@ class Reform::Contract < Disposable::Twin
|
|
11
11
|
validate!(nil).success?
|
12
12
|
end
|
13
13
|
|
14
|
-
# The #errors method will be removed in Reform
|
14
|
+
# The #errors method will be removed in Reform 3.0 core.
|
15
15
|
def errors(*args)
|
16
16
|
Result::Errors.new(@result, self)
|
17
17
|
end
|
@@ -22,7 +22,11 @@ class Reform::Contract < Disposable::Twin
|
|
22
22
|
@result
|
23
23
|
end
|
24
24
|
|
25
|
-
def
|
25
|
+
def custom_errors
|
26
|
+
@result.to_results.select { |result| result.is_a? Reform::Contract::CustomError }
|
27
|
+
end
|
28
|
+
|
29
|
+
def validate!(name, pointers = [])
|
26
30
|
# run local validations. this could be nested schemas, too.
|
27
31
|
local_errors_by_group = Reform::Validation::Groups::Validate.(self.class.validation_groups, self).compact # TODO: discss compact
|
28
32
|
|
@@ -33,10 +37,10 @@ class Reform::Contract < Disposable::Twin
|
|
33
37
|
nested_errors = validate_nested!(pointers_for_nested)
|
34
38
|
|
35
39
|
# Result: unified interface #success?, #messages, etc.
|
36
|
-
@result = Result.new(local_errors_by_group + pointers, nested_errors)
|
40
|
+
@result = Result.new(custom_errors + local_errors_by_group + pointers, nested_errors)
|
37
41
|
end
|
38
42
|
|
39
|
-
|
43
|
+
private
|
40
44
|
|
41
45
|
# Recursively call validate! on nested forms.
|
42
46
|
# A pointer keeps an entire result object (e.g. Dry result) and
|
@@ -46,11 +50,11 @@ class Reform::Contract < Disposable::Twin
|
|
46
50
|
|
47
51
|
schema.each(twin: true) do |dfn|
|
48
52
|
# on collections, this calls validate! on each item form.
|
49
|
-
Disposable::Twin::PropertyProcessor.new(dfn, self).()
|
53
|
+
Disposable::Twin::PropertyProcessor.new(dfn, self).() do |form, i|
|
50
54
|
nested_pointers = pointers.collect { |pointer| pointer.advance(dfn[:name].to_sym, i) }.compact # pointer contains fragment for us, so go deeper
|
51
55
|
|
52
56
|
arr << form.validate!(dfn[:name], nested_pointers)
|
53
|
-
|
57
|
+
end
|
54
58
|
end
|
55
59
|
|
56
60
|
arr
|
data/lib/reform/errors.rb
CHANGED
@@ -12,15 +12,14 @@ class Reform::Contract::Result::Errors
|
|
12
12
|
# PROTOTYPING. THIS WILL GO TO A SEPARATE GEM IN REFORM 2.4/3.0.
|
13
13
|
DottedErrors = ->(form, prefix, hash) do
|
14
14
|
result = form.to_result
|
15
|
-
result.messages.collect { |k,v| hash[
|
15
|
+
result.messages.collect { |k, v| hash[[*prefix, k].join(".").to_sym] = v }
|
16
16
|
|
17
|
-
form.schema.each(twin: true)
|
17
|
+
form.schema.each(twin: true) do |dfn|
|
18
18
|
Disposable::Twin::PropertyProcessor.new(dfn, form).() do |frm, i|
|
19
|
-
|
20
|
-
DottedErrors.(
|
21
|
-
DottedErrors.(form.send(dfn[:name]), [*prefix, dfn[:name]], hash)
|
19
|
+
form_obj = i ? form.send(dfn[:name])[i] : form.send(dfn[:name])
|
20
|
+
DottedErrors.(form_obj, [*prefix, dfn[:name]], hash)
|
22
21
|
end
|
23
|
-
|
22
|
+
end
|
24
23
|
end
|
25
24
|
|
26
25
|
def messages(*args)
|
@@ -28,22 +27,35 @@ class Reform::Contract::Result::Errors
|
|
28
27
|
end
|
29
28
|
|
30
29
|
def full_messages
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
30
|
+
@dotted_errors.collect { |path, errors|
|
31
|
+
human_field = path.to_s.gsub(/([\.\_])+/, " ").gsub(/(\b\w)+/) { |s| s.capitalize }
|
32
|
+
errors.collect { |message| "#{human_field} #{message}" }
|
33
|
+
}.flatten
|
35
34
|
end
|
36
35
|
|
37
36
|
def [](name)
|
38
|
-
@dotted_errors[name]
|
37
|
+
@dotted_errors[name] || []
|
39
38
|
end
|
40
39
|
|
41
40
|
def size
|
42
41
|
messages.size
|
43
42
|
end
|
43
|
+
|
44
|
+
# needed for rails form helpers
|
45
|
+
def empty?
|
46
|
+
messages.empty?
|
47
|
+
end
|
48
|
+
|
49
|
+
# we need to delegate adding error to result because every time we call form.errors
|
50
|
+
# a new instance of this class is created so we need to update the @results array
|
51
|
+
# to be able to add custom errors here.
|
52
|
+
# This method will actually work only AFTER a validate call has been made
|
53
|
+
def add(key, error_test)
|
54
|
+
@result.add_error(key, error_test)
|
55
|
+
end
|
44
56
|
end
|
45
57
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
58
|
+
# Ensure that we can return Active Record compliant full messages when using dry
|
59
|
+
# we only want unique messages in our array
|
60
|
+
#
|
61
|
+
# @full_errors.add()
|
data/lib/reform/form.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
module Reform
|
2
2
|
class Form < Contract
|
3
|
+
class InvalidOptionsCombinationError < StandardError; end
|
4
|
+
|
3
5
|
def self.default_nested_class
|
4
6
|
Form
|
5
7
|
end
|
@@ -15,23 +17,32 @@ module Reform
|
|
15
17
|
|
16
18
|
module Property
|
17
19
|
# Add macro logic, e.g. for :populator.
|
18
|
-
|
20
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
21
|
+
def property(name, options = {}, &block)
|
22
|
+
if (options.keys & %i[skip_if populator]).size == 2
|
23
|
+
raise InvalidOptionsCombinationError.new(
|
24
|
+
"[Reform] #{self}:property:#{name} Do not use skip_if and populator together, use populator with skip! instead"
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
19
28
|
# if composition and inherited we also need this setting
|
20
29
|
# to correctly inherit modules
|
21
|
-
if options.key?(:on) && options.key?(:inherit)
|
22
|
-
options[:_inherited] = options[:inherit]
|
23
|
-
end
|
30
|
+
options[:_inherited] = options[:inherit] if options.key?(:on) && options.key?(:inherit)
|
24
31
|
|
25
32
|
if options.key?(:parse)
|
26
33
|
options[:deserializer] ||= {}
|
27
34
|
options[:deserializer][:writeable] = options.delete(:parse)
|
28
35
|
end
|
29
36
|
|
30
|
-
if options.key?(:writable)
|
31
|
-
|
37
|
+
options[:writeable] ||= options.delete(:writable) if options.key?(:writable)
|
38
|
+
|
39
|
+
# for virtual collection we need at least to have the collection equal to [] to
|
40
|
+
# avoid issue when the populator
|
41
|
+
if (options.keys & %i[collection virtual]).size == 2
|
42
|
+
options = { default: [] }.merge(options)
|
32
43
|
end
|
33
44
|
|
34
|
-
definition = super #
|
45
|
+
definition = super # letdisposable and declarative gems sort out inheriting of properties, and so on.
|
35
46
|
definition.merge!(deserializer: {}) unless definition[:deserializer] # always keep :deserializer per property.
|
36
47
|
|
37
48
|
deserializer_options = definition[:deserializer]
|
@@ -48,7 +59,7 @@ module Reform
|
|
48
59
|
external_populator = Populator::External.new
|
49
60
|
|
50
61
|
# always compute a parse_pipeline for each property of the deserializer and inject it via :parse_pipeline.
|
51
|
-
# first,
|
62
|
+
# first, letrepresentable compute the pipeline functions by invoking #parse_functions.
|
52
63
|
if definition[:nested]
|
53
64
|
parse_pipeline = ->(input, opts) do
|
54
65
|
functions = opts[:binding].send(:parse_functions)
|
@@ -65,7 +76,7 @@ module Reform
|
|
65
76
|
pipeline = Representable::Pipeline[*functions] # Pipeline[StopOnExcluded, AssignName, ReadFragment, StopOnNotFound, OverwriteOnNil, Collect[#<Representable::Function::CreateObject:0xa6148ec>, #<Representable::Function::Decorate:0xa6148b0>, Deserialize], Set]
|
66
77
|
|
67
78
|
# FIXME: this won't work with property :name, inherit: true (where there is a populator set already).
|
68
|
-
pipeline = Representable::Pipeline::Insert.(pipeline, external_populator,
|
79
|
+
pipeline = Representable::Pipeline::Insert.(pipeline, external_populator, replace: Representable::SetValue) if definition[:populator] # FIXME: only diff to options without :populator
|
69
80
|
pipeline
|
70
81
|
end
|
71
82
|
end
|
@@ -77,12 +88,12 @@ module Reform
|
|
77
88
|
deserializer_options.merge!(skip_parse: proc) # TODO: same with skip_parse ==> External
|
78
89
|
end
|
79
90
|
|
80
|
-
|
81
91
|
# per default, everything should be writeable for the deserializer (we're only writing on the form). however, allow turning it off.
|
82
|
-
deserializer_options.merge!(writeable: true) unless deserializer_options.
|
92
|
+
deserializer_options.merge!(writeable: true) unless deserializer_options.key?(:writeable)
|
83
93
|
|
84
94
|
definition
|
85
95
|
end
|
96
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
86
97
|
end
|
87
98
|
extend Property
|
88
99
|
|