Class: Formalist::Elements::Many

Inherits:
Formalist::Element show all
Defined in:
lib/formalist/elements/many.rb

Instance Attribute Summary collapse

Attributes inherited from Formalist::Element

#attributes, #children, #errors, #input, #name

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Formalist::Element

#==, fill, #type

Methods included from Formalist::Element::ClassInterface

#attribute, #attributes_schema, #type

Constructor Details

#initialize(child_template:, **args) ⇒ Many

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a new instance of Many.



28
29
30
31
# File 'lib/formalist/elements/many.rb', line 28

def initialize(child_template:, **args)
  @child_template = child_template
  super(**args)
end

Instance Attribute Details

#child_templateObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



19
20
21
# File 'lib/formalist/elements/many.rb', line 19

def child_template
  @child_template
end

Class Method Details

.build(children: [], **args) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



22
23
24
25
# File 'lib/formalist/elements/many.rb', line 22

def self.build(children: [], **args)
  child_template = children.dup
  super(child_template: child_template, **args)
end

Instance Method Details

#fill(input: {}, errors: {}) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/formalist/elements/many.rb', line 34

def fill(input: {}, errors: {})
  input = input.fetch(name) { [] }
  errors = errors[name] || {}

  # Errors look like this when they are on the array itself: ["size cannot be greater than 2"]
  # Errors look like this when they are on children: {0=>{:summary=>["must be filled"]}

  children = input.each_with_index.map { |child_input, index|
    child_errors = errors.is_a?(Hash) ? errors.fetch(index) { {} } : {}

    child_template.map { |child| child.fill(input: child_input, errors: child_errors) }
  }

  super(
    input: input,
    errors: errors,
    children: children,
    child_template: child_template,
  )
end

#to_astArray

Converts a collection of "many" repeating elements into an abstract syntax tree.

It takes the following format:

[:many, [params]]

With the following parameters:

  1. Collection name
  2. Custom form element type (or :many otherwise)
  3. Collection-level error messages
  4. Form element attributes
  5. Child element "template" (i.e. the form elements comprising a single entry in the collection of "many" elements, without any user data associated)
  6. Child elements, one for each of the entries in the input data (or none, if there is no or empty input data)

Examples:

"locations" collection

many.to_ast
# => [:many, [
  :locations,
  :many,
  ["locations size cannot be less than 3"],
  [:object, [
    [:allow_create, [:value, [true]]],
    [:allow_update, [:value, [true]]],
    [:allow_destroy, [:value, [true]]],
    [:allow_reorder, [:value, [true]]]
  ]],
  [
    [:field, [:name, :field, nil, [], [], [:object, []]]],
    [:field, [:address, :field, nil, [], [], [:object, []]]]
  ],
  [
    [
      [:field, [:name, :field, "Icelab Canberra", [], [], [:object, []]]],
      [:field, [:address, :field, "Canberra, ACT, Australia", [], [], [:object, []]]]
    ],
    [
      [:field, [:name, :field, "Icelab Melbourne", [], [], [:object, []]]],
      [:field, [:address, :field, "Melbourne, VIC, Australia", [], [], [:object, []]]]
    ]
  ]
]]

See Also:



107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/formalist/elements/many.rb', line 107

def to_ast
  local_errors = errors.is_a?(Array) ? errors : []

  [:many, [
    name,
    type,
    local_errors,
    Element::Attributes.new(attributes).to_ast,
    child_template.map(&:to_ast),
    children.map { |el_list| el_list.map(&:to_ast) },
  ]]
end