reform 2.2.4 → 2.3.1
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/.rubocop.yml +30 -0
- data/.rubocop_todo.yml +460 -0
- data/.travis.yml +11 -6
- data/Appraisals +8 -0
- data/CHANGES.md +54 -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 +18 -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 +46 -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 +15 -13
- data/test/benchmarking.rb +39 -6
- data/test/call_new_api.rb +23 -0
- data/test/{call_test.rb → call_old_api.rb} +4 -4
- data/test/changed_test.rb +8 -8
- data/test/coercion_test.rb +51 -19
- data/test/composition_new_api.rb +186 -0
- data/test/{composition_test.rb → composition_old_api.rb} +66 -31
- 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} +13 -13
- data/test/default_test.rb +2 -2
- data/test/deserialize_test.rb +11 -14
- data/test/errors_new_api.rb +225 -0
- data/test/errors_old_api.rb +230 -0
- data/test/feature_test.rb +8 -10
- 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} +5 -5
- data/test/form_option_new_api.rb +24 -0
- data/test/{form_option_test.rb → form_option_old_api.rb} +4 -4
- data/test/from_test.rb +9 -13
- 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} +20 -25
- data/test/module_old_api.rb +146 -0
- data/test/parse_option_test.rb +40 -0
- data/test/parse_pipeline_test.rb +3 -3
- data/test/populate_new_api.rb +304 -0
- data/test/{populate_test.rb → populate_old_api.rb} +83 -49
- data/test/populator_skip_test.rb +9 -9
- data/test/prepopulator_test.rb +8 -9
- data/test/read_only_test.rb +12 -1
- data/test/readable_test.rb +7 -7
- data/test/reform_new_api.rb +204 -0
- data/test/{reform_test.rb → reform_old_api.rb} +30 -51
- data/test/save_new_api.rb +101 -0
- data/test/{save_test.rb → save_old_api.rb} +32 -20
- data/test/setup_test.rb +8 -8
- data/test/{skip_if_test.rb → skip_if_new_api.rb} +23 -12
- data/test/skip_if_old_api.rb +92 -0
- data/test/skip_setter_and_getter_test.rb +3 -4
- data/test/test_helper.rb +25 -14
- data/test/validate_new_api.rb +408 -0
- data/test/{validate_test.rb → validate_old_api.rb} +59 -69
- data/test/validation/dry_validation_new_api.rb +836 -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 +35 -6
- metadata +127 -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/deprecation_test.rb +0 -27
- data/test/errors_test.rb +0 -165
- data/test/inherit_test.rb +0 -119
- data/test/readonly_test.rb +0 -14
- data/test/validation/dry_test.rb +0 -60
- data/test/validation/dry_validation_test.rb +0 -352
- data/test/validation/errors.yml +0 -4
@@ -0,0 +1,61 @@
|
|
1
|
+
# Provides the old API for Rails and friends.
|
2
|
+
# Note that this might become an optional "deprecation" gem in Reform 3.
|
3
|
+
class Reform::Contract::Result::Errors
|
4
|
+
def initialize(result, form)
|
5
|
+
@result = result # DISCUSS: we don't use this ATM?
|
6
|
+
@form = form
|
7
|
+
@dotted_errors = {} # Reform does not endorse this style of error msgs.
|
8
|
+
|
9
|
+
DottedErrors.(@form, [], @dotted_errors)
|
10
|
+
end
|
11
|
+
|
12
|
+
# PROTOTYPING. THIS WILL GO TO A SEPARATE GEM IN REFORM 2.4/3.0.
|
13
|
+
DottedErrors = ->(form, prefix, hash) do
|
14
|
+
result = form.to_result
|
15
|
+
result.messages.collect { |k, v| hash[[*prefix, k].join(".").to_sym] = v }
|
16
|
+
|
17
|
+
form.schema.each(twin: true) do |dfn|
|
18
|
+
Disposable::Twin::PropertyProcessor.new(dfn, form).() do |frm, i|
|
19
|
+
form_obj = i ? form.send(dfn[:name])[i] : form.send(dfn[:name])
|
20
|
+
DottedErrors.(form_obj, [*prefix, dfn[:name]], hash)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def messages(*args)
|
26
|
+
@dotted_errors
|
27
|
+
end
|
28
|
+
|
29
|
+
def full_messages
|
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
|
34
|
+
end
|
35
|
+
|
36
|
+
def [](name)
|
37
|
+
@dotted_errors[name] || []
|
38
|
+
end
|
39
|
+
|
40
|
+
def size
|
41
|
+
messages.size
|
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
|
56
|
+
end
|
57
|
+
|
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,8 +17,32 @@ module Reform
|
|
15
17
|
|
16
18
|
module Property
|
17
19
|
# Add macro logic, e.g. for :populator.
|
18
|
-
|
19
|
-
|
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
|
+
|
28
|
+
# if composition and inherited we also need this setting
|
29
|
+
# to correctly inherit modules
|
30
|
+
options[:_inherited] = options[:inherit] if options.key?(:on) && options.key?(:inherit)
|
31
|
+
|
32
|
+
if options.key?(:parse)
|
33
|
+
options[:deserializer] ||= {}
|
34
|
+
options[:deserializer][:writeable] = options.delete(:parse)
|
35
|
+
end
|
36
|
+
|
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)
|
43
|
+
end
|
44
|
+
|
45
|
+
definition = super # letdisposable and declarative gems sort out inheriting of properties, and so on.
|
20
46
|
definition.merge!(deserializer: {}) unless definition[:deserializer] # always keep :deserializer per property.
|
21
47
|
|
22
48
|
deserializer_options = definition[:deserializer]
|
@@ -33,10 +59,10 @@ module Reform
|
|
33
59
|
external_populator = Populator::External.new
|
34
60
|
|
35
61
|
# always compute a parse_pipeline for each property of the deserializer and inject it via :parse_pipeline.
|
36
|
-
# first,
|
62
|
+
# first, letrepresentable compute the pipeline functions by invoking #parse_functions.
|
37
63
|
if definition[:nested]
|
38
|
-
parse_pipeline = ->(input,
|
39
|
-
functions =
|
64
|
+
parse_pipeline = ->(input, opts) do
|
65
|
+
functions = opts[:binding].send(:parse_functions)
|
40
66
|
pipeline = Representable::Pipeline[*functions] # Pipeline[StopOnExcluded, AssignName, ReadFragment, StopOnNotFound, OverwriteOnNil, Collect[#<Representable::Function::CreateObject:0xa6148ec>, #<Representable::Function::Decorate:0xa6148b0>, Deserialize], Set]
|
41
67
|
|
42
68
|
pipeline = Representable::Pipeline::Insert.(pipeline, external_populator, replace: Representable::CreateObject::Instance)
|
@@ -45,12 +71,12 @@ module Reform
|
|
45
71
|
pipeline = Representable::Pipeline::Insert.(pipeline, Representable::SetValue, delete: true) # FIXME: only diff to options without :populator
|
46
72
|
end
|
47
73
|
else
|
48
|
-
parse_pipeline = ->(input,
|
49
|
-
functions =
|
74
|
+
parse_pipeline = ->(input, opts) do
|
75
|
+
functions = opts[:binding].send(:parse_functions)
|
50
76
|
pipeline = Representable::Pipeline[*functions] # Pipeline[StopOnExcluded, AssignName, ReadFragment, StopOnNotFound, OverwriteOnNil, Collect[#<Representable::Function::CreateObject:0xa6148ec>, #<Representable::Function::Decorate:0xa6148b0>, Deserialize], Set]
|
51
77
|
|
52
78
|
# FIXME: this won't work with property :name, inherit: true (where there is a populator set already).
|
53
|
-
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
|
54
80
|
pipeline
|
55
81
|
end
|
56
82
|
end
|
@@ -62,12 +88,12 @@ module Reform
|
|
62
88
|
deserializer_options.merge!(skip_parse: proc) # TODO: same with skip_parse ==> External
|
63
89
|
end
|
64
90
|
|
65
|
-
|
66
91
|
# per default, everything should be writeable for the deserializer (we're only writing on the form). however, allow turning it off.
|
67
|
-
deserializer_options.merge!(writeable: true) unless deserializer_options.
|
92
|
+
deserializer_options.merge!(writeable: true) unless deserializer_options.key?(:writeable)
|
68
93
|
|
69
94
|
definition
|
70
95
|
end
|
96
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
71
97
|
end
|
72
98
|
extend Property
|
73
99
|
|
data/lib/reform/form/call.rb
CHANGED
@@ -16,13 +16,13 @@ module Reform::Form::Composition
|
|
16
16
|
#
|
17
17
|
# class CoverSongForm < Reform::Form
|
18
18
|
# model :song, on: :cover_song
|
19
|
-
def model(main_model, options={})
|
19
|
+
def model(main_model, options = {})
|
20
20
|
super
|
21
21
|
|
22
22
|
composition_model = options[:on] || main_model
|
23
23
|
|
24
24
|
# FIXME: this should just delegate to :model as in FB, and the comp would take care of it internally.
|
25
|
-
[
|
25
|
+
%i[persisted? to_key to_param].each do |method|
|
26
26
|
define_method method do
|
27
27
|
model[composition_model].send(method)
|
28
28
|
end
|
data/lib/reform/form/dry.rb
CHANGED
@@ -1,67 +1,19 @@
|
|
1
1
|
require "dry-validation"
|
2
|
-
require "dry/validation/
|
2
|
+
require "dry/validation/version"
|
3
3
|
require "reform/validation"
|
4
|
+
require "reform/form/dry/input_hash"
|
4
5
|
|
5
6
|
module Reform::Form::Dry
|
6
7
|
def self.included(includer)
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
Reform::Contract::Errors.new(self)
|
14
|
-
end
|
15
|
-
|
16
|
-
module ClassMethods
|
17
|
-
def validation_group_class
|
18
|
-
Group
|
19
|
-
end
|
8
|
+
if Gem::Version.new(Dry::Validation::VERSION) > Gem::Version.new("0.13.3")
|
9
|
+
require "reform/form/dry/new_api"
|
10
|
+
validations = Reform::Form::Dry::NewApi::Validations
|
11
|
+
else
|
12
|
+
require "reform/form/dry/old_api"
|
13
|
+
validations = Reform::Form::Dry::OldApi::Validations
|
20
14
|
end
|
21
15
|
|
22
|
-
|
23
|
-
|
24
|
-
end
|
25
|
-
|
26
|
-
class Group
|
27
|
-
def initialize
|
28
|
-
@schemas = []
|
29
|
-
end
|
30
|
-
|
31
|
-
def instance_exec(&block)
|
32
|
-
@schemas << block
|
33
|
-
@validator = Builder.new(@schemas.dup).validation_graph
|
34
|
-
end
|
35
|
-
|
36
|
-
def call(fields, reform_errors, form)
|
37
|
-
# a message item looks like: {:confirm_password=>["confirm_password size cannot be less than 2"]}
|
38
|
-
@validator.with(form: form).call(fields).messages.each do |field, dry_error|
|
39
|
-
dry_error.each do |attr_error|
|
40
|
-
reform_errors.add(field, attr_error)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
class Builder < Array
|
46
|
-
def initialize(array)
|
47
|
-
super(array)
|
48
|
-
@validator = Dry::Validation.Form({}, &shift)
|
49
|
-
end
|
50
|
-
|
51
|
-
def validation_graph
|
52
|
-
build_graph(@validator)
|
53
|
-
end
|
54
|
-
|
55
|
-
|
56
|
-
private
|
57
|
-
|
58
|
-
def build_graph(validator)
|
59
|
-
if empty?
|
60
|
-
return validator
|
61
|
-
end
|
62
|
-
build_graph(Dry::Validation.Schema(validator, {}, &shift))
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
16
|
+
includer.send :include, validations
|
17
|
+
includer.extend validations::ClassMethods
|
66
18
|
end
|
67
19
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Reform::Form::Dry
|
2
|
+
module InputHash
|
3
|
+
private
|
4
|
+
|
5
|
+
# if dry_error is a hash rather than an array then it contains
|
6
|
+
# the messages for a nested property
|
7
|
+
# these messages need to be added to the correct collection
|
8
|
+
# objects.
|
9
|
+
|
10
|
+
# collections:
|
11
|
+
# {0=>{:name=>["must be filled"]}, 1=>{:name=>["must be filled"]}}
|
12
|
+
|
13
|
+
# Objects:
|
14
|
+
# {:name=>["must be filled"]}
|
15
|
+
# simply load up the object and attach the message to it
|
16
|
+
|
17
|
+
# we can't use to_nested_hash as it get's messed up by composition.
|
18
|
+
def input_hash(form)
|
19
|
+
hash = form.class.nested_hash_representer.new(form).to_hash
|
20
|
+
symbolize_hash(hash)
|
21
|
+
end
|
22
|
+
|
23
|
+
# dry-v needs symbolized keys
|
24
|
+
# TODO: Don't do this here... Representers??
|
25
|
+
def symbolize_hash(old_hash)
|
26
|
+
old_hash.each_with_object({}) do |(k, v), new_hash|
|
27
|
+
new_hash[k.to_sym] = if v.is_a?(Hash)
|
28
|
+
symbolize_hash(v)
|
29
|
+
elsif v.is_a?(Array)
|
30
|
+
v.map { |h| h.is_a?(Hash) ? symbolize_hash(h) : h }
|
31
|
+
else
|
32
|
+
v
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
::Dry::Validation.load_extensions(:hints)
|
2
|
+
|
3
|
+
module Reform::Form::Dry
|
4
|
+
module NewApi
|
5
|
+
|
6
|
+
class Contract < ::Dry::Validation::Contract
|
7
|
+
end
|
8
|
+
|
9
|
+
module Validations
|
10
|
+
module ClassMethods
|
11
|
+
def validation_group_class
|
12
|
+
Group
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.included(includer)
|
17
|
+
includer.extend(ClassMethods)
|
18
|
+
end
|
19
|
+
|
20
|
+
class Group
|
21
|
+
include InputHash
|
22
|
+
|
23
|
+
def initialize(options = {})
|
24
|
+
@validator = options.fetch(:schema, Contract)
|
25
|
+
@schema_inject_params = options.fetch(:with, {})
|
26
|
+
end
|
27
|
+
|
28
|
+
def instance_exec(&block)
|
29
|
+
@block = block
|
30
|
+
end
|
31
|
+
|
32
|
+
def call(form)
|
33
|
+
# when passing options[:schema] the class instance is already created so we just need to call
|
34
|
+
# "call"
|
35
|
+
if @validator.is_a?(Class) && @validator <= ::Dry::Validation::Contract
|
36
|
+
dynamic_options = {form: form}
|
37
|
+
inject_options = @schema_inject_params.merge(dynamic_options)
|
38
|
+
@validator = @validator.build(inject_options, &@block)
|
39
|
+
end
|
40
|
+
|
41
|
+
@validator.call(input_hash(form))
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Reform::Form::Dry
|
2
|
+
module OldApi
|
3
|
+
class Schema < Dry::Validation::Schema
|
4
|
+
end
|
5
|
+
|
6
|
+
module Validations
|
7
|
+
module ClassMethods
|
8
|
+
def validation_group_class
|
9
|
+
Group
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.included(includer)
|
14
|
+
includer.extend(ClassMethods)
|
15
|
+
end
|
16
|
+
|
17
|
+
class Group
|
18
|
+
include InputHash
|
19
|
+
|
20
|
+
def initialize(options = {})
|
21
|
+
options ||= {}
|
22
|
+
schema_class = options[:schema] || Reform::Form::Dry::OldApi::Schema
|
23
|
+
@validator = Dry::Validation.Schema(schema_class, build: false)
|
24
|
+
|
25
|
+
@schema_inject_params = options[:with] || {}
|
26
|
+
end
|
27
|
+
|
28
|
+
def instance_exec(&block)
|
29
|
+
@validator = Dry::Validation.Schema(@validator, build: false, &block)
|
30
|
+
# inject the keys into the configure block automatically
|
31
|
+
keys = @schema_inject_params.keys
|
32
|
+
@validator.class_eval do
|
33
|
+
configure do
|
34
|
+
keys.each { |k| option k }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def call(form)
|
40
|
+
dynamic_options = {}
|
41
|
+
dynamic_options[:form] = form if @schema_inject_params[:form]
|
42
|
+
inject_options = @schema_inject_params.merge(dynamic_options)
|
43
|
+
|
44
|
+
# TODO: only pass submitted values to Schema#call?
|
45
|
+
dry_result = call_schema(inject_options, input_hash(form))
|
46
|
+
# dry_messages = dry_result.messages
|
47
|
+
|
48
|
+
return dry_result
|
49
|
+
|
50
|
+
_reform_errors = Reform::Contract::Errors.new(dry_result) # TODO: dry should be merged here.
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def call_schema(inject_options, input)
|
56
|
+
@validator.new(@validator.rules, inject_options).(input)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -7,7 +7,7 @@
|
|
7
7
|
class Reform::Form::Populator
|
8
8
|
def initialize(user_proc)
|
9
9
|
@user_proc = user_proc # the actual `populator: ->{}` block from the user, via ::property.
|
10
|
-
@value = Declarative::Option(user_proc, instance_exec: true) # we can now process Callable, procs, :symbol.
|
10
|
+
@value = Declarative::Option(user_proc, instance_exec: true, callable: Object) # we can now process Callable, procs, :symbol.
|
11
11
|
end
|
12
12
|
|
13
13
|
def call(input, options)
|
@@ -26,13 +26,11 @@ class Reform::Form::Populator
|
|
26
26
|
twin
|
27
27
|
end
|
28
28
|
|
29
|
-
private
|
29
|
+
private
|
30
|
+
|
30
31
|
def call!(options)
|
31
32
|
form = options[:represented]
|
32
|
-
|
33
|
-
deprecate_positional_args(form, @user_proc, options) do
|
34
|
-
@value.(form, options)
|
35
|
-
end
|
33
|
+
@value.(form, options) # Declarative::Option call.
|
36
34
|
end
|
37
35
|
|
38
36
|
def handle_fail(twin, options)
|
@@ -40,20 +38,9 @@ private
|
|
40
38
|
end
|
41
39
|
|
42
40
|
def get(options)
|
43
|
-
|
44
|
-
end
|
45
|
-
|
46
|
-
def deprecate_positional_args(form, proc, options) # TODO: remove in 2.2.
|
47
|
-
arity = proc.is_a?(Symbol) ? form.method(proc).arity : proc.arity
|
48
|
-
return yield if arity == 1
|
49
|
-
warn "[Reform] Positional arguments for :populator and friends are deprecated. Please use ->(options) and enjoy the rest of your day. Learn more at http://trailblazerb.org/gems/reform/upgrading-guide.html#to-21"
|
50
|
-
args = []
|
51
|
-
args << options[:index] if options[:index]
|
52
|
-
args << options[:representable_options]
|
53
|
-
form.instance_exec(options[:fragment], options[:model], *args, &proc)
|
41
|
+
Representable::GetValue.(nil, options)
|
54
42
|
end
|
55
43
|
|
56
|
-
|
57
44
|
class IfEmpty < self # Populator
|
58
45
|
def call!(options)
|
59
46
|
binding, twin, index, fragment = options[:binding], options[:model], options[:index], options[:fragment] # TODO: remove once we drop 2.0.
|
@@ -73,7 +60,8 @@ private
|
|
73
60
|
end
|
74
61
|
end
|
75
62
|
|
76
|
-
|
63
|
+
private
|
64
|
+
|
77
65
|
def run!(form, fragment, options)
|
78
66
|
return @user_proc.new if @user_proc.is_a?(Class) # handle populate_if_empty: Class. this excludes using Callables, though.
|
79
67
|
|
@@ -89,18 +77,14 @@ private
|
|
89
77
|
|
90
78
|
@value.(form, options[:fragment], options[:user_options])
|
91
79
|
end
|
92
|
-
|
93
80
|
end
|
94
81
|
|
95
82
|
# Sync (default) blindly grabs the corresponding form twin and returns it. This might imply that nil is returned,
|
96
83
|
# and in turn #validate! is called on nil.
|
97
84
|
class Sync < self
|
98
85
|
def call!(options)
|
99
|
-
if options[:binding].array?
|
100
|
-
|
101
|
-
else
|
102
|
-
options[:model]
|
103
|
-
end
|
86
|
+
return options[:model][options[:index]] if options[:binding].array?
|
87
|
+
options[:model]
|
104
88
|
end
|
105
89
|
end
|
106
90
|
|
@@ -116,8 +100,8 @@ private
|
|
116
100
|
# (which population is) to the form.
|
117
101
|
class External
|
118
102
|
def call(input, options)
|
119
|
-
options[:represented].class.definitions
|
120
|
-
|
103
|
+
options[:represented].class.definitions
|
104
|
+
.get(options[:binding][:name])[:internal_populator].(input, options)
|
121
105
|
end
|
122
106
|
end
|
123
107
|
end
|