Class: DSLCompose::Parser::ForChildrenOfParser

Inherits:
Object
  • Object
show all
Defined in:
lib/dsl_compose/parser/for_children_of_parser.rb,
lib/dsl_compose/parser/for_children_of_parser/descendants.rb,
lib/dsl_compose/parser/for_children_of_parser/for_dsl_parser.rb,
lib/dsl_compose/parser/for_children_of_parser/for_dsl_parser/for_method_parser.rb

Defined Under Namespace

Classes: AllBlockParametersMustBeKeywordParametersError, ClassDoesNotUseDSLComposeError, Descendants, ForDSLParser, NoBlockProvided, NoChildClassError

Instance Method Summary collapse

Constructor Details

#initialize(base_class, final_children_only, skip_classes = [], &block) ⇒ ForChildrenOfParser

This class will yield to the provided block for each descendant class of the provided base_class

For example:

class BaseClass

include DSLCompose::Composer
define_dsl :my_foo_dsl

end

class ChildClass < BaseClass

my_foo_dsl

end

class GrandchildClass < ChildClass end

parser.for_children_of BaseClass do |child_class:|

# this will yield for ChildClass and GrandchildClass

and



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/dsl_compose/parser/for_children_of_parser.rb', line 38

def initialize base_class, final_children_only, skip_classes = [], &block
  # assert the provided class has the DSLCompose::Composer module installed
  unless base_class.respond_to? :dsls
    raise ClassDoesNotUseDSLComposeError, base_class
  end

  @base_class = base_class

  # assert that a block was provided
  unless block
    raise NoBlockProvided
  end

  # if any arguments were provided, then assert that they are valid
  if block&.parameters&.any?
    # all parameters must be keyword arguments
    if block.parameters.filter { |p| p.first != :keyreq }.any?
      raise AllBlockParametersMustBeKeywordParametersError, "All block parameters must be keyword parameters, i.e. `for_children_of FooClass do |base_class:|`"
    end
  end

  # yeild the block for all descendants of the provided base_class
  Descendants.new(base_class, final_children_only, skip_classes).classes.each do |child_class|
    # determine which arguments to send to the block
    args = {}
    if BlockArguments.accepts_argument?(:child_class, &block)
      args[:child_class] = child_class
    end

    # set the child_class in an instance variable so that method calls to
    # `for_dsl` from within the block will have access to it
    @child_class = child_class

    # yield the block in the context of this class
    instance_exec(**args, &block)
  end
end