Sha256: 42ffef96a53c6e3db20eb96fc6398b0de76d215e6ab419c04ffbb304d184c592

Contents?: true

Size: 1.82 KB

Versions: 2

Compression:

Stored size: 1.82 KB

Contents

require "formalist/element/definition"

module Formalist
  class Form
    class DefinitionContext
      DuplicateDefinitionError = Class.new(StandardError)

      attr_reader :elements
      attr_reader :container
      attr_reader :permissions

      def initialize(options = {})
        @elements = []
        @container = options.fetch(:container)
        @permissions = options.fetch(:permissions)
      end

      def with(options = {})
        %i[container permissions].each do |attr|
          options[attr] ||= send(attr)
        end

        self.class.new(options)
      end

      def call(&block)
        instance_eval(&block) if block
        self
      end

      def dep(name)
        Element::Definition::Deferred.new(name)
      end

      def method_missing(name, *args, &block)
        return add_element(name, *args, &block) if element_type_exists?(name)
        super
      end

      def respond_to_missing?(name)
        element_type_exists?(name)
      end

      private

      def element_type_exists?(type)
        container.key?(type)
      end

      def add_element(element_type, *args, &block)
        type = container[element_type]
        raise ArgumentError, "element +#{element_type}+ is not permitted in this context" unless permissions.permitted?(type)

        # Work with top-level args and a trailing attributes hash
        args = args.dup
        attributes = args.last.is_a?(Hash) ? args.pop : {}

        children = with(permissions: type.permitted_children).call(&block).elements
        definition = Element::Definition.new(type, *args, attributes, children)

        if elements.any? { |el| el == definition }
          raise DuplicateDefinitionError, "element +#{element_type} #{args.map(&:inspect).join(', ')}+ is already defined in this context"
        end

        elements << definition
      end
    end
  end
end

Version data entries

2 entries across 2 versions & 1 rubygems

Version Path
formalist-0.3.0 lib/formalist/form/definition_context.rb
formalist-0.2.3 lib/formalist/form/definition_context.rb