class Stall::Checkout::StepForm

Attributes

clear_cart_errors[R]
object[R]
step[R]

Public Class Methods

build(&block) click to toggle source

Build an dynamic StepForm subclass with the given block as the body of the class

# File lib/stall/checkout/step_form.rb, line 40
def self.build(&block)
  Class.new(StepForm, &block)
end
nested(type, &block) click to toggle source
# File lib/stall/checkout/step_form.rb, line 32
def self.nested(type, &block)
  self.nested_forms ||= {}
  nested_forms[type] = build(&block)
end
new(object, step, clear: true) click to toggle source
# File lib/stall/checkout/step_form.rb, line 12
def initialize(object, step, clear: true)
  @object = object
  @step = step
  @clear_cart_errors = clear
end

Public Instance Methods

method_missing(method, *args, &block) click to toggle source
Calls superclass method
# File lib/stall/checkout/step_form.rb, line 44
def method_missing(method, *args, &block)
  if object.respond_to?(method, true)
    object.send(method, *args, &block)
  elsif step.respond_to?(method, true)
    step.send(method, *args, &block)
  else
    super
  end
end
model_name() click to toggle source

Override model name instanciation to add a name, since the form classes are anonymous, and ActiveModel::Name does not support unnamed classes

# File lib/stall/checkout/step_form.rb, line 56
def model_name
  @model_name ||= ActiveModel::Name.new(self, nil, self.class.name)
end
validate() click to toggle source

Runs form and nested forms validations and returns wether they all passed or not

Only clear validation errors on the cart if needed, allowing to run cart validations before the step ones, passing clear: false in the form constructor, aggregating both validation sources' errors

# File lib/stall/checkout/step_form.rb, line 25
def validate
  errors.clear if clear_cart_errors
  run_validations!
  validate_nested_forms
  !errors.any?
end

Private Instance Methods

validate_nested_forms() click to toggle source

Validates all registered nested forms

Note : We use `forms.map.all?` instead if `forms.all?` to ensure all the validations are called and the iteration does not stop as soon as a validation fails

# File lib/stall/checkout/step_form.rb, line 68
def validate_nested_forms
  # If no nested forms are present in the class, just return true since
  # no validation should be tested
  return true unless nested_forms

  # Run all validations on all nested forms and ensure they're all valid
  nested_forms.map do |name, form|
    if object.respond_to?(name) && (resource = object.send(name)) &&
      !(resource.respond_to?(:marked_for_destruction?) && resource.marked_for_destruction?)
    then
      valid = Array.wrap(resource).map { |m| form.new(m, step, clear: @clear_cart_errors).validate }.all?
      # Bubble up nested errors
      errors.add(name, :invalid) unless valid

      valid
    else
      # Nested validations shouldn't be run on undefined relations
      true
    end
  end.all?
end