formalist 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +7 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +21 -0
  5. data/.yardopts +1 -0
  6. data/CHANGELOG.md +62 -0
  7. data/Gemfile +1 -2
  8. data/bin/console +13 -0
  9. data/formalist.gemspec +33 -0
  10. data/lib/formalist/definition.rb +65 -0
  11. data/lib/formalist/element/class_interface.rb +7 -59
  12. data/lib/formalist/element.rb +37 -19
  13. data/lib/formalist/elements/attr.rb +8 -20
  14. data/lib/formalist/elements/compound_field.rb +5 -4
  15. data/lib/formalist/elements/field.rb +5 -12
  16. data/lib/formalist/elements/group.rb +6 -5
  17. data/lib/formalist/elements/many.rb +28 -29
  18. data/lib/formalist/elements/section.rb +6 -10
  19. data/lib/formalist/elements/standard/multi_upload_field.rb +8 -0
  20. data/lib/formalist/elements/standard/rich_text_area.rb +40 -0
  21. data/lib/formalist/elements/standard/search_multi_selection_field.rb +20 -0
  22. data/lib/formalist/elements/standard/search_selection_field.rb +20 -0
  23. data/lib/formalist/elements/standard/tags_field.rb +16 -0
  24. data/lib/formalist/elements/standard/upload_field.rb +8 -0
  25. data/lib/formalist/elements/standard.rb +4 -0
  26. data/lib/formalist/form/validity_check.rb +54 -0
  27. data/lib/formalist/form.rb +49 -17
  28. data/lib/formalist/rich_text/embedded_form_compiler.rb +86 -0
  29. data/lib/formalist/rich_text/embedded_forms_container/mixin.rb +42 -0
  30. data/lib/formalist/rich_text/embedded_forms_container/registration.rb +30 -0
  31. data/lib/formalist/rich_text/embedded_forms_container.rb +9 -0
  32. data/lib/formalist/rich_text/rendering/embedded_form_renderer.rb +25 -0
  33. data/lib/formalist/rich_text/rendering/html_compiler.rb +100 -0
  34. data/lib/formalist/rich_text/rendering/html_renderer.rb +186 -0
  35. data/lib/formalist/rich_text/validity_check.rb +48 -0
  36. data/lib/formalist/types.rb +8 -7
  37. data/lib/formalist/version.rb +1 -1
  38. metadata +54 -31
  39. data/Gemfile.lock +0 -105
  40. data/lib/formalist/element/definition.rb +0 -55
  41. data/lib/formalist/element/permitted_children.rb +0 -46
  42. data/lib/formalist/form/definition_context.rb +0 -69
  43. data/lib/formalist/form/result.rb +0 -24
  44. data/spec/examples.txt +0 -8
  45. data/spec/integration/dependency_injection_spec.rb +0 -54
  46. data/spec/integration/form_spec.rb +0 -104
  47. data/spec/spec_helper.rb +0 -109
  48. data/spec/support/constants.rb +0 -11
  49. data/spec/unit/elements/standard/check_box_spec.rb +0 -33
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 3a25ed29e5310c5707691b6e42089f845acda96d
4
- data.tar.gz: ae3ec66e1957062442a116068671e7924009a49d
2
+ SHA256:
3
+ metadata.gz: 1ef816ca82a212ab5b8eba60fd57c68393d1443876b527b85b507c933974fdb9
4
+ data.tar.gz: 539b605da36b8383a5645fd191920e9c16c7ff7c6f1582dc435bf521a96366a8
5
5
  SHA512:
6
- metadata.gz: 75991212d87c5a71fc2b8805fc9b1905c271d50e29684ffb65484ae37e70e3adada85a561e42feab49414da1fb91c4ba7d038ee82c30c352f07c2318c706d8b6
7
- data.tar.gz: 344e4392c1b1d8749c2520397451be67b143a5338153dfafb15ba2dbc6a3958607d20fef7f05e280df31a29300451fb28b3ffe778e0e618c0c17b47ec2c9d4b8
6
+ metadata.gz: 9c23dd6b7f40ead5fa9fd81008bef073a7b94fe3e98738f3a03a22733e7a732b5e1ba92e0ec26cc66cf41380a96155c643144e90f450500f8039e8fa0e663087
7
+ data.tar.gz: e58de764348c401f5321864f761e421415536a31e607ea13567d2e0374c563125162c395f4ed0d70488c026c44b841f655fd43fba359e8cc18565a0349f3aa39
data/.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ /.byebug_history
2
+ /.yardoc
3
+ /doc
4
+ /coverage
5
+ /spec/examples.txt
6
+ /pkg
7
+ /Gemfile.lock
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,21 @@
1
+ language: ruby
2
+ dist: trusty
3
+ sudo: false
4
+ cache: bundler
5
+ before_install:
6
+ - gem update bundler
7
+ script:
8
+ - bundle exec rake
9
+ after_success:
10
+ # Send coverage report from the job #1 == current MRI release
11
+ - '[ "${TRAVIS_JOB_NUMBER#*.}" = "1" ] && [ "$TRAVIS_BRANCH" = "master" ] && bundle exec codeclimate-test-reporter'
12
+ rvm:
13
+ - 2.4.0
14
+ - 2.3.3
15
+ - 2.2.6
16
+ - jruby-9.1.6.0
17
+ addons:
18
+ code_climate:
19
+ repo_token: 2c2c7c253435c02667371778ca886b069d4d24590748fbd7396b9b080016bfa7
20
+ notifications:
21
+ email: false
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --markup=markdown
data/CHANGELOG.md ADDED
@@ -0,0 +1,62 @@
1
+ # 0.4.0 / 2018-03-28
2
+
3
+ ### Added
4
+
5
+ - `rich_text_area` field type, support for embedding and validating forms within rich text areas, and rendering the rich text from its native draft.js AST format to HTML
6
+ - `search_selection_field` and `multi_search_selection_field` field types
7
+ - Various improvements to the upload fields, including support for passing `presign_options`
8
+
9
+ ### Changed
10
+
11
+ - [BREAKING] Form definition blocks are now evaluated within the context of the form instance's `self`, which mean dependencies can be injected into the form object and accessed from the form definition block. `#dep` within the definition block has thusly been removed.
12
+ - [BREAKING] `Formalist::Form` should now be instantiated (`form = MyForm.new`) and then filled with `form.fill(input: input_data, errors: error_messages)`. `Form#fill` returns a copy of the form object with all the elements filled with the input data and error messages as required. `Form#call` has been removed, along with `Formalist::Form::Result` (which was the object returned from `#call`).
13
+
14
+ ### Removed
15
+
16
+ - Form elements no longer have a `permitted_children` config. For now, this should be handled by convention only.
17
+
18
+ # 0.3.0 / 2016-05-04
19
+
20
+ Add support for upload and multi upload fields.
21
+
22
+ # 0.2.3 / 2016-04-07
23
+
24
+ Default check_box element values to false.
25
+
26
+ # 0.2.2 / 2016-02-23
27
+
28
+ Remove local type coercion using dry-data. We rely on a `Dry::Validation::Schema` to do this now. The form definition API has not yet changed, though. We still require field types to be specified, but there is no longer any restriction over what is entered. We'll remove this in a future release, once we can infer types from the schema.
29
+
30
+ # 0.2.1 / 2016-02-23
31
+
32
+ Fix issue where form could not be built with input data with native data types (it presuming input would be HTML form-style input everywhere).
33
+
34
+ Add default (empty) input data argument for `Form#build`. This allows you simply to call `MyForm.build` for creating a "new" form (i.e. one without any existing input data).
35
+
36
+ # 0.2.0 / 2016-02-22
37
+
38
+ Require a dry-validation schema for each form. The schema should completely represent the form's expected data structure.
39
+
40
+ Update the API to better support the two main use cases for a form. First, to prepare a form with sane, initial input from your database and send it to a view for rendering:
41
+
42
+ ```ruby
43
+ my_form = MyForm.new(my_schema)
44
+ my_form.build(input) # returns a `Formalist::Form::Result`
45
+ ```
46
+
47
+ Then, to receive the data from the posted form, coerce it and validate it (and potentially re-display the form with errors):
48
+
49
+ ```ruby
50
+ my_form = MyForm.new(my_schema)
51
+ my_form.receive(input).validate # returns a `Formalist::Form::ValidatedResult`
52
+ ```
53
+
54
+ The main differences are as such:
55
+
56
+ * `#build` expects already-clean (e.g. properly structured and typed) data
57
+ * `#receive` expects the kind of data that your form will submit, and will then coerce it according to the validation schema, and then send the sanitised output to `#build`
58
+ * Calling `#validate` on a result object will validate the input data and include any error messages in its AST
59
+
60
+ # 0.1.0 / 2016-01-18
61
+
62
+ Initial release.
data/Gemfile CHANGED
@@ -5,8 +5,7 @@ gemspec
5
5
  group :test do
6
6
  gem "codeclimate-test-reporter", require: nil
7
7
  gem "dry-auto_inject"
8
- gem "dry-validation", git: "https://github.com/dryrb/dry-validation", branch: "master"
9
- gem "dry-types", git: "https://github.com/dryrb/dry-types", branch: "master"
8
+ gem "dry-validation", "~> 0.11"
10
9
  end
11
10
 
12
11
  group :tools do
data/bin/console ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+
5
+ require "pry"
6
+ begin
7
+ require "byebug"
8
+ rescue LoadError; end
9
+ require "formalist"
10
+ require "formalist/elements/standard"
11
+ require "dry-validation"
12
+
13
+ Pry.start
data/formalist.gemspec ADDED
@@ -0,0 +1,33 @@
1
+ lib = File.expand_path("../lib", __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require "formalist/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "formalist"
7
+ spec.version = Formalist::VERSION
8
+ spec.authors = ["Tim Riley"]
9
+ spec.email = ["tim@icelab.com.au"]
10
+ spec.license = "MIT"
11
+
12
+ spec.summary = "Flexible form builder"
13
+ spec.homepage = "https://github.com/icelab/formalist"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
16
+ spec.bindir = 'exe'
17
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
18
+ spec.require_paths = ['lib']
19
+
20
+ spec.required_ruby_version = ">= 2.2.0"
21
+
22
+ spec.add_runtime_dependency "dry-configurable", "~> 0.7"
23
+ spec.add_runtime_dependency "dry-core", "~> 0.4"
24
+ spec.add_runtime_dependency "dry-container", "~> 0.6"
25
+ spec.add_runtime_dependency "dry-types", "~> 0.12"
26
+ spec.add_runtime_dependency "inflecto"
27
+
28
+ spec.add_development_dependency "bundler", "~> 1.10"
29
+ spec.add_development_dependency "rake", "~> 10.4.2"
30
+ spec.add_development_dependency "rspec", "~> 3.3.0"
31
+ spec.add_development_dependency "simplecov", "~> 0.13.0"
32
+ spec.add_development_dependency "yard"
33
+ end
@@ -0,0 +1,65 @@
1
+ module Formalist
2
+ class Definition
3
+ DuplicateElementError = Class.new(StandardError)
4
+
5
+ attr_reader :form
6
+ attr_reader :config
7
+ attr_reader :elements
8
+
9
+ def initialize(form, config, &block)
10
+ @form = form
11
+ @config = config
12
+ @elements = []
13
+
14
+ instance_eval(&block) if block
15
+ end
16
+
17
+ def with(**new_options, &block)
18
+ new_config = new_options.each_with_object(config.dup) { |(key, value), config|
19
+ config.send :"#{key}=", value
20
+ }
21
+
22
+ self.class.new(form, new_config, &block)
23
+ end
24
+
25
+ def method_missing(name, *args, &block)
26
+ if element_type?(name)
27
+ add_element(name, *args, &block)
28
+ elsif form.respond_to?(name)
29
+ form.send(name, *args, &block)
30
+ else
31
+ super
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def respond_to_missing?(name, _include_private = false)
38
+ element_type?(name) || form.respond_to?(name)
39
+ end
40
+
41
+ def element_type?(type)
42
+ config.elements_container.key?(type)
43
+ end
44
+
45
+ def add_element(type, *args, &block)
46
+ element_name = args.shift unless args.first.is_a?(Hash)
47
+ element_attrs = args.last.is_a?(Hash) ? args.last : {}
48
+
49
+ if element_name && elements.any? { |element| element.name == element_name }
50
+ raise DuplicateElementError, "element +#{element_name}+ is already defined in this context"
51
+ end
52
+
53
+ element_class = config.elements_container[type]
54
+ element_children = with(&block).elements
55
+
56
+ element = element_class.build(
57
+ name: element_name,
58
+ attributes: element_attrs,
59
+ children: element_children,
60
+ )
61
+
62
+ elements << element
63
+ end
64
+ end
65
+ end
@@ -1,28 +1,23 @@
1
1
  require "inflecto"
2
- require "formalist/element/permitted_children"
3
2
 
4
3
  module Formalist
5
4
  class Element
6
5
  # Class-level API for form elements.
7
6
  module ClassInterface
8
- # Returns the element's type, which is a symbolized, camlized
7
+ # Returns the element's type, which is a symbolized, underscored
9
8
  # representation of the element's class name.
10
9
  #
11
- # This is a critical hook for customising form rendering when using
12
- # custom form elements, since the type in this case will be based on the
13
- # name of form element's sublass.
10
+ # This is important for form rendering when using custom form elements,
11
+ # since the type in this case will be based on the name of form element's
12
+ # sublass.
14
13
  #
15
- # @example Basic element
16
- # Formalist::Elements::Field.type # => :field
14
+ # @example Basic element Formalist::Elements::Field.type # => :field
17
15
  #
18
- # @example Custom element
19
- # class MyField < Formalist::Elements::Field
20
- # end
16
+ # @example Custom element class MyField < Formalist::Elements::Field end
21
17
  #
22
18
  # MyField.type # => :my_field
23
19
  #
24
- # @!scope class
25
- # @return [Symbol] the element type.
20
+ # @!scope class @return [Symbol] the element type.
26
21
  def type
27
22
  Inflecto.underscore(Inflecto.demodulize(name)).to_sym
28
23
  end
@@ -71,53 +66,6 @@ module Formalist
71
66
  super_schema.merge(@attributes_schema || {})
72
67
  end
73
68
 
74
- # Sets or fetches the policy for the element's permitted child form elements.
75
- #
76
- # @overload permitted_children(policy)
77
- # Set a policy for whether the element permits child form elements.
78
- #
79
- # Specify `:all` to allow all children, or `:none` to permit no
80
- # children.
81
- #
82
- # @example Permitting all children
83
- # permitted_children :all
84
- #
85
- # @example Permitting no children
86
- # permitted_children :none
87
- #
88
- # @return void
89
- #
90
- # @overload permitted_children(element_type, ...)
91
- # Permit the element to contain only the specified element types as children.
92
- #
93
- # @example
94
- # permit_children :section, :field
95
- #
96
- # @param element_type [Symbol] the name of a child element type to permit
97
- # @param ... [Symbol] more child element types to permit
98
- # @return void
99
- #
100
- # @overload permitted_children
101
- # Returns the permitted child element types for the element.
102
- #
103
- # If no `permitted_children` policy was previously specified, then it
104
- # allows all children by default.
105
- #
106
- # @return [#permitted?] permissions object.
107
- #
108
- # @see Formalist::Element::PermittedChildren
109
- #
110
- # @!scope class
111
- def permitted_children(*args)
112
- return @permitted_children ||= PermittedChildren.all if args.empty?
113
-
114
- @permitted_children = if %i[all none].include?(args.first)
115
- PermittedChildren.send(args.first)
116
- else
117
- PermittedChildren[args]
118
- end
119
- end
120
-
121
69
  private
122
70
 
123
71
  # @!scope class
@@ -7,42 +7,60 @@ module Formalist
7
7
  extend ClassInterface
8
8
 
9
9
  # @api private
10
- attr_reader :attributes, :children, :input, :errors
10
+ attr_reader :name, :attributes, :children, :input, :errors
11
11
 
12
12
  # @api private
13
- def initialize(*args, attributes, children, input, errors)
13
+ def self.build(**args)
14
+ new(args)
15
+ end
16
+
17
+ # @api private
18
+ def self.fill(input: {}, errors: {}, **args)
19
+ new(args).fill(input: input, errors: errors)
20
+ end
21
+
22
+ # @api private
23
+ def initialize(name: nil, attributes: {}, children: [], input: nil, errors: [])
24
+ @name = Types::ElementName[name]
25
+
14
26
  # Set supplied attributes or their defaults
15
- full_attributes = self.class.attributes_schema.each_with_object({}) { |(name, defn), memo|
27
+ all_attributes = self.class.attributes_schema.each_with_object({}) { |(name, defn), memo|
16
28
  value = attributes[name] || defn[:default]
17
29
  memo[name] = value unless value.nil?
18
30
  }
19
31
 
20
32
  # Then run them through the schema
21
- @attributes = Types::Hash.schema(self.class.attributes_schema.map { |name, defn| [name, defn[:type]] }.to_h).(full_attributes)
33
+ @attributes = Types::Hash.schema(
34
+ self.class.attributes_schema.map { |name, defn| [name, defn[:type]] }.to_h
35
+ )[all_attributes]
22
36
 
23
- @children = []
37
+ @children = children
24
38
  @input = input
25
39
  @errors = errors
26
40
  end
27
41
 
28
- # Returns the element's type, which is a symbolized, camlized
29
- # representation of the element's class name.
30
- #
31
- # This is a critical hook for customising form rendering when using custom
32
- # form elements, since the type in this case will be based on the name of
33
- # form element's sublass.
34
- #
35
- # @example Basic element
36
- # field.type # => :field
37
- #
38
- # @example Custom element
39
- # my_field.type # => :my_field
40
- #
41
- # @return [Symbol] the element type.
42
+ def fill(input: {}, errors: {}, **args)
43
+ return self if input == @input && errors == @errors
44
+
45
+ args = {
46
+ name: @name,
47
+ attributes: @attributes,
48
+ children: @children,
49
+ input: input,
50
+ errors: errors,
51
+ }.merge(args)
52
+
53
+ self.class.new(args)
54
+ end
55
+
42
56
  def type
43
57
  self.class.type
44
58
  end
45
59
 
60
+ def ==(other)
61
+ name && type == other.type && name == other.name
62
+ end
63
+
46
64
  # @abstract
47
65
  def to_ast
48
66
  raise NotImplementedError
@@ -4,21 +4,17 @@ require "formalist/types"
4
4
  module Formalist
5
5
  class Elements
6
6
  class Attr < Element
7
- permitted_children :all
8
-
9
- # @api private
10
- attr_reader :name
11
-
12
7
  attribute :label, Types::String
13
8
 
14
- # @api private
15
- def initialize(*args, attributes, children, input, errors)
16
- super
9
+ def fill(input:, errors:)
10
+ input = input[name] || {}
11
+ errors = errors[name] || {}
17
12
 
18
- @name = Types::ElementName.(args.first)
19
- @input = input.fetch(@name, {})
20
- @errors = errors[@name]
21
- @children = build_children(children)
13
+ children = self.children.map { |child|
14
+ child.fill(input: input, errors: errors)
15
+ }
16
+
17
+ super(input: input, errors: errors, children: children)
22
18
  end
23
19
 
24
20
  # Converts the attribute into an abstract syntax tree.
@@ -61,14 +57,6 @@ module Formalist
61
57
  children.map(&:to_ast),
62
58
  ]]
63
59
  end
64
-
65
- private
66
-
67
- def build_children(definitions)
68
- child_errors = errors.is_a?(Hash) ? errors : {}
69
-
70
- definitions.map { |definition| definition.(input, child_errors) }
71
- end
72
60
  end
73
61
  end
74
62
  end
@@ -4,11 +4,12 @@ require "formalist/types"
4
4
  module Formalist
5
5
  class Elements
6
6
  class CompoundField < Element
7
- permitted_children :field
7
+ def fill(input: {}, errors: {})
8
+ children = self.children.map { |child|
9
+ child.fill(input: input, errors: errors)
10
+ }
8
11
 
9
- def initialize(*args, attributes, children, input, errors)
10
- super
11
- @children = children.map { |definition| definition.(input, errors) }
12
+ super(input: input, errors: errors, children: children)
12
13
  end
13
14
 
14
15
  # Converts the compound field into an abstract syntax tree.
@@ -4,11 +4,6 @@ require "formalist/types"
4
4
  module Formalist
5
5
  class Elements
6
6
  class Field < Element
7
- permitted_children :none
8
-
9
- # @api private
10
- attr_reader :name
11
-
12
7
  attribute :label, Types::String
13
8
  attribute :hint, Types::String
14
9
  attribute :placeholder, Types::String
@@ -18,13 +13,11 @@ module Formalist
18
13
  # @api private
19
14
  attr_reader :predicates
20
15
 
21
- # @api private
22
- def initialize(*args, attributes, children, input, errors)
23
- super
24
-
25
- @name = Types::ElementName.(args.first)
26
- @input = input[@name] if input
27
- @errors = errors[@name].to_a
16
+ def fill(input: {}, errors: {})
17
+ super(
18
+ input: input[name],
19
+ errors: errors[name].to_a,
20
+ )
28
21
  end
29
22
 
30
23
  # Converts the field into an abstract syntax tree.
@@ -4,13 +4,14 @@ require "formalist/types"
4
4
  module Formalist
5
5
  class Elements
6
6
  class Group < Element
7
- permitted_children :attr, :compound_field, :field, :many
8
-
9
7
  attribute :label, Types::String
10
8
 
11
- def initialize(*args, attributes, children, input, errors)
12
- super
13
- @children = children.map { |definition| definition.(input, errors) }
9
+ def fill(input: {}, errors: {})
10
+ children = self.children.map { |child|
11
+ child.fill(input: input, errors: errors)
12
+ }
13
+
14
+ super(input: input, errors: errors, children: children)
14
15
  end
15
16
 
16
17
  # Converts the group into an abstract syntax tree.
@@ -4,11 +4,6 @@ require "formalist/types"
4
4
  module Formalist
5
5
  class Elements
6
6
  class Many < Element
7
- permitted_children :attr, :compound_field, :group, :field
8
-
9
- # @api private
10
- attr_reader :name
11
-
12
7
  attribute :label, Types::String
13
8
  attribute :action_label, Types::String
14
9
  attribute :placeholder, Types::String
@@ -18,14 +13,35 @@ module Formalist
18
13
  attr_reader :child_template
19
14
 
20
15
  # @api private
21
- def initialize(*args, attributes, children, input, errors)
22
- super
16
+ def self.build(children: [], **args)
17
+ child_template = children.dup
18
+ super(child_template: child_template, **args)
19
+ end
20
+
21
+ # @api private
22
+ def initialize(child_template:, **args)
23
+ @child_template = child_template
24
+ super(**args)
25
+ end
26
+
27
+ # @api private
28
+ def fill(input: {}, errors: {})
29
+ input = input.fetch(name) { [] }
30
+ errors = errors.fetch(name) { {} }
31
+
32
+ children = input.each_with_index.map { |child_input, index|
33
+ # Child errors look like this: {0=>{:summary=>["must be filled"]}
34
+ child_errors = errors.fetch(index) { {} }
23
35
 
24
- @name = Types::ElementName.(args.first)
25
- @input = input.fetch(name, [])
26
- @errors = errors[@name]
27
- @child_template = build_child_template(children)
28
- @children = build_children(children)
36
+ child_template.map { |child| child.fill(input: child_input, errors: child_errors) }
37
+ }
38
+
39
+ super(
40
+ input: input,
41
+ errors: errors,
42
+ children: children,
43
+ child_template: child_template,
44
+ )
29
45
  end
30
46
 
31
47
  # Until we can put defaults on `Types::Bool`, supply them here
@@ -103,23 +119,6 @@ module Formalist
103
119
  children.map { |el_list| el_list.map(&:to_ast) },
104
120
  ]]
105
121
  end
106
-
107
- private
108
-
109
- def build_child_template(definitions)
110
- definitions.map { |el| el.({}, {})}
111
- end
112
-
113
- def build_children(definitions)
114
- # Child errors look like this: {0=>{:summary=>["must be filled"]}
115
- child_errors = errors.is_a?(Hash) ? errors : {}
116
-
117
- input.each_with_index.map { |child_input, index|
118
- errors = child_errors.fetch(index, {})
119
-
120
- definitions.map { |el| el.(child_input, errors) }
121
- }
122
- end
123
122
  end
124
123
  end
125
124
  end
@@ -4,18 +4,14 @@ require "formalist/types"
4
4
  module Formalist
5
5
  class Elements
6
6
  class Section < Element
7
- permitted_children :all
8
-
9
- # @api private
10
- attr_reader :name
11
-
12
7
  attribute :label, Types::String
13
8
 
14
- def initialize(*args, attributes, children, input, errors)
15
- super
16
-
17
- @name = Types::ElementName.(args.first)
18
- @children = children.map { |definition| definition.(input, errors) }
9
+ def fill(input: {}, errors: {})
10
+ super(
11
+ input: input,
12
+ errors: errors,
13
+ children: children.map { |child| child.fill(input: input, errors: errors) },
14
+ )
19
15
  end
20
16
 
21
17
  # Converts the section into an abstract syntax tree.
@@ -6,6 +6,14 @@ module Formalist
6
6
  class Elements
7
7
  class MultiUploadField < Field
8
8
  attribute :presign_url, Types::String
9
+ attribute :presign_options, Types::Hash
10
+ attribute :render_uploaded_as, Types::String
11
+ attribute :upload_prompt, Types::String
12
+ attribute :upload_action_label, Types::String
13
+ attribute :max_file_size, Types::String
14
+ attribute :max_file_size_message, Types::String
15
+ attribute :permitted_file_type_message, Types::String
16
+ attribute :permitted_file_type_regex, Types::String
9
17
  end
10
18
 
11
19
  register :multi_upload_field, MultiUploadField