class CLI::Mastermind::ParentPlan

Plan implementation designed to hold other plans forming the intermediate nodes on the tree of loaded plans. @private

Attributes

children[R]

Used in the interactive plan selector to display child plans

Public Class Methods

new(name, description=nil, filename=nil, &block) click to toggle source

@param (see Plan) @see Plan

Calls superclass method CLI::Mastermind::Plan::new
# File lib/cli/mastermind/parent_plan.rb, line 16
def initialize(name, description=nil, filename=nil, &block)
  super

  @children = {}
end

Public Instance Methods

[](name)
Alias for: get_child
add_children(plans) click to toggle source

Adds new children to this plan

@param plans [Array<Plan>] the plans to add @return [Void]

# File lib/cli/mastermind/parent_plan.rb, line 43
def add_children(plans)
  raise InvalidPlanError, 'Cannot add child plans to a plan with an action' unless @block.nil?
  plans.each(&method(:incorporate_plan))
end
dig(name)
Alias for: get_child
get_child(name) click to toggle source

Get the child plan with the specified name.

This method also checks plan aliases, so the given name can also be a plan's alias.

@param name [String] the name of the child plan to retrieve @return [Plan,nil] the child plan, if it exists

# File lib/cli/mastermind/parent_plan.rb, line 29
def get_child(name)
  return @children[name] if @children.has_key? name
  @children.each_value.find { |child| child.aliases.include? name }
end
Also aliased as: [], dig
has_children?() click to toggle source

@return [Boolean] if this plan has any children

# File lib/cli/mastermind/parent_plan.rb, line 49
def has_children?
  @children.any?
end

Private Instance Methods

incorporate_plan(plan) click to toggle source

Adds a new plan to the children hash

@param plan [Plan] the plan to add @see resolve_conflicts

# File lib/cli/mastermind/parent_plan.rb, line 59
def incorporate_plan(plan)
  @children[plan.name] = resolve_conflicts(plan.name, plan)
end
resolve_conflicts(key, plan) click to toggle source

Resolves plan name collisions.

If two child plans have the same name, how they're resolved depends on what kind of plan they are. The following situations are convered by this method:

1) Both plans have children.

* In this case, the incoming plan's children are merged into the existing
  plan and the incoming plan is discarded.

2) One or both plans have no children.

* In this case, it's assumed that the childless plans are executable.
  A warning is printed an the incoming plan replaces the existing plan.

@param key [String] the key the incoming plan will be stored under @param plan [Plan] the incoming plan @return [Plan] the plan to store

# File lib/cli/mastermind/parent_plan.rb, line 80
      def resolve_conflicts(key, plan)
        # If this namespace isn't taken we're good
        return plan unless @children.has_key?(key)

        # Otherwise, we need to handle a name collision
        existing_plan = @children[key]

        # If both plans have children, we merge them together
        if existing_plan.has_children? and plan.has_children?
          existing_plan.add_children plan.children.values

          return existing_plan
        end

        # Otherwise, the plan defined later wins and overwrites the existing plan

        # Warn the user that this is happening, unless we're running tests.
        warn <<~PLAN_COLLISON.strip unless defined? RSpec
               Plan name collision encountered when loading plans from "#{plan.filename}" that cannot be merged.
               "#{key}" was previously defined in "#{existing_plan.filename}".
               Plan "#{key}" from "#{plan.filename}" will be used instead.
             PLAN_COLLISON

        plan
      end