reform 2.3.0.rc1 → 2.3.0.rc2
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 +4 -4
- data/.gitignore +2 -0
- data/.rubocop.yml +30 -0
- data/.rubocop_todo.yml +460 -0
- data/.travis.yml +26 -11
- data/CHANGES.md +25 -2
- data/Gemfile +6 -3
- data/ISSUE_TEMPLATE.md +1 -1
- data/README.md +2 -4
- data/Rakefile +18 -9
- data/lib/reform/contract.rb +7 -7
- data/lib/reform/contract/custom_error.rb +41 -0
- data/lib/reform/contract/validate.rb +9 -5
- 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 +10 -86
- data/lib/reform/form/dry/input_hash.rb +37 -0
- data/lib/reform/form/dry/new_api.rb +58 -0
- data/lib/reform/form/dry/old_api.rb +61 -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 -3
- data/lib/reform/version.rb +1 -1
- data/reform.gemspec +10 -9
- data/test/benchmarking.rb +10 -11
- data/test/call_new_api.rb +23 -0
- data/test/{call_test.rb → call_old_api.rb} +3 -3
- data/test/changed_test.rb +7 -7
- data/test/coercion_test.rb +50 -18
- data/test/composition_new_api.rb +186 -0
- data/test/{composition_test.rb → composition_old_api.rb} +23 -26
- data/test/contract/custom_error_test.rb +55 -0
- data/test/contract_new_api.rb +77 -0
- data/test/{contract_test.rb → contract_old_api.rb} +8 -8
- data/test/default_test.rb +1 -1
- data/test/deserialize_test.rb +8 -11
- data/test/errors_new_api.rb +225 -0
- data/test/errors_old_api.rb +230 -0
- data/test/feature_test.rb +7 -9
- data/test/fixtures/dry_error_messages.yml +5 -2
- 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} +2 -2
- data/test/form_option_new_api.rb +24 -0
- data/test/{form_option_test.rb → form_option_old_api.rb} +1 -1
- data/test/from_test.rb +8 -12
- data/test/inherit_new_api.rb +105 -0
- data/test/{inherit_test.rb → inherit_old_api.rb} +10 -17
- data/test/module_new_api.rb +137 -0
- data/test/{module_test.rb → module_old_api.rb} +19 -15
- data/test/parse_option_test.rb +5 -5
- data/test/parse_pipeline_test.rb +2 -2
- data/test/populate_new_api.rb +304 -0
- data/test/{populate_test.rb → populate_old_api.rb} +28 -34
- data/test/populator_skip_test.rb +1 -2
- data/test/prepopulator_test.rb +5 -6
- data/test/read_only_test.rb +12 -1
- data/test/readable_test.rb +5 -5
- data/test/reform_new_api.rb +204 -0
- data/test/{reform_test.rb → reform_old_api.rb} +17 -23
- data/test/save_new_api.rb +101 -0
- data/test/{save_test.rb → save_old_api.rb} +10 -13
- data/test/setup_test.rb +6 -6
- data/test/{skip_if_test.rb → skip_if_new_api.rb} +20 -9
- data/test/skip_if_old_api.rb +92 -0
- data/test/skip_setter_and_getter_test.rb +2 -3
- data/test/test_helper.rb +13 -5
- data/test/validate_new_api.rb +408 -0
- data/test/{validate_test.rb → validate_old_api.rb} +43 -53
- data/test/validation/dry_validation_new_api.rb +826 -0
- data/test/validation/{dry_validation_test.rb → dry_validation_old_api.rb} +223 -116
- data/test/validation/result_test.rb +20 -22
- data/test/validation_library_provided_test.rb +3 -3
- data/test/virtual_test.rb +46 -6
- data/test/writeable_test.rb +7 -7
- metadata +101 -51
- data/test/errors_test.rb +0 -180
- data/test/readonly_test.rb +0 -14
data/.travis.yml
CHANGED
|
@@ -2,16 +2,31 @@ language: ruby
|
|
|
2
2
|
cache: bundler
|
|
3
3
|
bundler_args: --without benchmarks tools
|
|
4
4
|
rvm:
|
|
5
|
-
-
|
|
6
|
-
- 2.
|
|
7
|
-
- 2.
|
|
8
|
-
|
|
5
|
+
- ruby-head
|
|
6
|
+
- 2.5
|
|
7
|
+
- 2.4
|
|
8
|
+
env:
|
|
9
|
+
- "DRY_VALIDATION='~> 1.3.0'"
|
|
10
|
+
- "DRY_VALIDATION='~> 1.2.0'"
|
|
11
|
+
- "DRY_VALIDATION='~> 1.1.0'"
|
|
12
|
+
- "DRY_VALIDATION='~> 1.0.0'"
|
|
13
|
+
- "DRY_VALIDATION='~> 0.13.0'"
|
|
14
|
+
- "DRY_VALIDATION='~> 0.12.0'"
|
|
9
15
|
matrix:
|
|
10
16
|
fast_finish: true
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
allow_failures:
|
|
18
|
+
- rvm: ruby-head
|
|
19
|
+
include:
|
|
20
|
+
- { rvm: 2.2, env: "DRY_VALIDATION='~> 0.11.0'" }
|
|
21
|
+
- { rvm: 2.3, env: "DRY_VALIDATION='~> 0.12.0'" }
|
|
22
|
+
- { rvm: 2.3, env: "DRY_VALIDATION='~> 0.13.0'" }
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
# maybe move this to slack in a private channel
|
|
26
|
+
# notifications:
|
|
27
|
+
# webhooks:
|
|
28
|
+
# urls:
|
|
29
|
+
# - https://webhooks.gitter.im/e/680e86d98056f2ae2fd7
|
|
30
|
+
# on_success: change # options: [always|never|change] default: always
|
|
31
|
+
# on_failure: always # options: [always|never|change] default: always
|
|
32
|
+
# on_start: never # options: [always|never|change] default: always
|
data/CHANGES.md
CHANGED
|
@@ -17,10 +17,33 @@ You can upgrade from 2.2.0 without worries.
|
|
|
17
17
|
* Reform now maintains a generic `Dry::Schema` class for global schema configuration. Can be overridden via `::validation`.
|
|
18
18
|
* 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
19
|
* [private] `Group#call` API now is: `call(form, errors)`.
|
|
20
|
-
*
|
|
21
|
-
|
|
20
|
+
* Modify `Form#valid?` - simply calls `validate({})`.
|
|
22
21
|
* In `:if` for validation groups, you now get a hash of result objects, not just true/false.
|
|
22
|
+
* Allow adding a custom error AFTER validate has been already called
|
|
23
|
+
|
|
24
|
+
Compatibility with `dry-validation` with 1.x:
|
|
25
|
+
* [CHANGE] seems like "custom" predicate are not supported by `dry-schema` anymore or better the same result is reached using the `rule` method:
|
|
26
|
+
Something like this:
|
|
27
|
+
```ruby
|
|
28
|
+
validation do
|
|
29
|
+
def a_song?(value)
|
|
30
|
+
value == :really_cool_song
|
|
31
|
+
end
|
|
23
32
|
|
|
33
|
+
required(:songs).filled(:a_song?)
|
|
34
|
+
end
|
|
35
|
+
```
|
|
36
|
+
will be something like:
|
|
37
|
+
```ruby
|
|
38
|
+
validation do
|
|
39
|
+
required(:songs).filled
|
|
40
|
+
|
|
41
|
+
rule(:songs) do
|
|
42
|
+
key.failure(:a_song?) unless value == :really_cool_song
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
```
|
|
46
|
+
* [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
47
|
|
|
25
48
|
## 2.2.4
|
|
26
49
|
|
data/Gemfile
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
source
|
|
1
|
+
source "https://rubygems.org"
|
|
2
2
|
|
|
3
3
|
gemspec
|
|
4
4
|
|
|
5
|
-
gem "minitest-line"
|
|
6
|
-
gem 'byebug'
|
|
7
5
|
# gem "disposable", path: "../disposable"
|
|
8
6
|
|
|
7
|
+
# just trying to add `dry-monads` correct version in base on dry-validation
|
|
8
|
+
dry_v_version = ENV.fetch('DRY_VALIDATION', '~> 0.13.0')
|
|
9
|
+
dry_m_version = "~> #{dry_v_version.gsub("~>", "").to_f}.0"
|
|
10
|
+
gem 'dry-monads', dry_m_version if dry_v_version.gsub("~>", "").to_f >= 1
|
|
11
|
+
gem 'dry-validation', ENV.fetch('DRY_VALIDATION', '~> 0.13.0')
|
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/README.md
CHANGED
|
@@ -315,16 +315,14 @@ 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
|
-

|
|
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
|
|
data/Rakefile
CHANGED
|
@@ -1,15 +1,24 @@
|
|
|
1
1
|
require "bundler/gem_tasks"
|
|
2
|
-
require
|
|
2
|
+
require "rake/testtask"
|
|
3
|
+
require "rubocop/rake_task"
|
|
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
|
+
dry_v_version = ENV.fetch("DRY_VALIDATION", "~> 0.13.0")
|
|
14
|
+
api = dry_v_version.gsub("~>", "").to_f >= 1.0 ? "new" : "old"
|
|
15
|
+
TEST_WITH_OLD_AND_NEW_API.map { |file| "test/#{file}_#{api}_api.rb" }
|
|
9
16
|
end
|
|
10
17
|
|
|
11
|
-
Rake::TestTask.new(:
|
|
12
|
-
test.libs <<
|
|
13
|
-
test.test_files = FileList[
|
|
18
|
+
Rake::TestTask.new(:test) do |test|
|
|
19
|
+
test.libs << "test"
|
|
20
|
+
test.test_files = FileList["test/*_test.rb"] + FileList["test/validation/*_test.rb"] + dry_v_test_files
|
|
14
21
|
test.verbose = true
|
|
15
22
|
end
|
|
23
|
+
|
|
24
|
+
RuboCop::RakeTask.new(:rubocop)
|
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
|
|
@@ -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
|
|