Class: Yes::Core::Commands::CommandGroup

Inherits:
Object
  • Object
show all
Defined in:
lib/yes/core/commands/command_group.rb

Overview

Base class for aggregate-DSL command groups.

A CommandGroup represents a compound, transactional action declared inside an aggregate via the ‘command_group :name do … end` macro. It references its sub-commands by symbol (not by class constant) so declaration order in the aggregate body does not matter — resolution happens lazily against the Yes configuration registry.

The legacy Group is intentionally untouched and continues to serve the stateless command flow.

Constant Summary collapse

Attributes =

Reuse the legacy Group’s reserved-key Attributes struct — the shape is identical for both group flavours.

Yes::Core::Commands::Group::Attributes

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(params) ⇒ CommandGroup

Returns a new instance of CommandGroup.

Parameters:

  • params (Hash)

    flat / partially-nested input payload, optionally carrying reserved keys (transaction, origin, batch_id, metadata, command_id, es_encrypted)



99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/yes/core/commands/command_group.rb', line 99

def initialize(params)
  @group_attributes = Attributes.new(params.slice(*Yes::Core::Command::RESERVED_KEYS))
  @payload = params.except(*Yes::Core::Command::RESERVED_KEYS).symbolize_keys
  @normalized_payload = GroupPayloadNormalizer.call(
    params,
    command_contexts: self.class.command_contexts,
    own_context_subjects: self.class.own_context_subjects,
    own_context: self.class.own_context,
    own_subject: self.class.own_subject
  )
  @commands = build_commands
end

Class Attribute Details

.aggregateString

Returns the group’s owning aggregate, e.g. “Apprenticeship”.

Returns:

  • (String)

    the group’s owning aggregate, e.g. “Apprenticeship”



26
27
28
# File 'lib/yes/core/commands/command_group.rb', line 26

def aggregate
  @aggregate
end

.contextString

Returns the group’s owning context, e.g. “Companies”.

Returns:

  • (String)

    the group’s owning context, e.g. “Companies”



23
24
25
# File 'lib/yes/core/commands/command_group.rb', line 23

def context
  @context
end

.group_nameSymbol

Returns the group’s name as defined by ‘command_group :name`.

Returns:

  • (Symbol)

    the group’s name as defined by ‘command_group :name`



29
30
31
# File 'lib/yes/core/commands/command_group.rb', line 29

def group_name
  @group_name
end

.sub_command_namesObject



35
36
37
# File 'lib/yes/core/commands/command_group.rb', line 35

def sub_command_names
  @sub_command_names ||= []
end

Instance Attribute Details

#commandsArray<Yes::Core::Command> (readonly)

Returns sub-command instances in execution order.

Returns:



87
88
89
# File 'lib/yes/core/commands/command_group.rb', line 87

def commands
  @commands
end

#group_attributesAttributes (readonly)

Returns the reserved-key attributes of the group.

Returns:

  • (Attributes)

    the reserved-key attributes of the group



84
85
86
# File 'lib/yes/core/commands/command_group.rb', line 84

def group_attributes
  @group_attributes
end

#normalized_payloadHash (readonly)

Returns the payload normalized into per-context/per-subject buckets. Used internally to construct sub-command instances and exposed so callers can introspect the group’s per-sub-command shape.

Returns:

  • (Hash)

    the payload normalized into per-context/per-subject buckets. Used internally to construct sub-command instances and exposed so callers can introspect the group’s per-sub-command shape.



81
82
83
# File 'lib/yes/core/commands/command_group.rb', line 81

def normalized_payload
  @normalized_payload
end

#payloadHash (readonly)

Returns the flat input payload (reserved keys stripped). This is what guard blocks see via ‘payload.<attr>` through PayloadProxy.

Returns:

  • (Hash)

    the flat input payload (reserved keys stripped). This is what guard blocks see via ‘payload.<attr>` through PayloadProxy.



76
77
78
# File 'lib/yes/core/commands/command_group.rb', line 76

def payload
  @payload
end

Class Method Details

.command_contextsArray<Symbol>

Returns unique contexts of all sub-commands.

Returns:

  • (Array<Symbol>)

    unique contexts of all sub-commands



61
62
63
# File 'lib/yes/core/commands/command_group.rb', line 61

def command_contexts
  sub_command_classes.map { |c| c.name.split('::').first.underscore.to_sym }.uniq
end

.own_contextSymbol

Returns the own context as a snake-cased symbol.

Returns:

  • (Symbol)

    the own context as a snake-cased symbol



40
41
42
# File 'lib/yes/core/commands/command_group.rb', line 40

def own_context
  context.to_s.underscore.to_sym
end

.own_context_subjectsArray<Symbol>

Returns subjects in the own context.

Returns:

  • (Array<Symbol>)

    subjects in the own context



66
67
68
69
70
71
# File 'lib/yes/core/commands/command_group.rb', line 66

def own_context_subjects
  sub_command_classes.
    select { |c| c.name.split('::').first.underscore.to_sym == own_context }.
    map    { |c| c.name.split('::')[1].underscore.to_sym }.
    uniq
end

.own_subjectSymbol

Returns the own subject (aggregate name) as a snake-cased symbol.

Returns:

  • (Symbol)

    the own subject (aggregate name) as a snake-cased symbol



45
46
47
# File 'lib/yes/core/commands/command_group.rb', line 45

def own_subject
  aggregate.to_s.underscore.to_sym
end

.sub_command_classesArray<Class>

Resolves the sub-command classes lazily so declaration order in the aggregate body does not matter.

Returns:

  • (Array<Class>)

    sub-command classes in declaration order



53
54
55
56
57
58
# File 'lib/yes/core/commands/command_group.rb', line 53

def sub_command_classes
  sub_command_names.map do |name|
    Yes::Core.configuration.aggregate_class(context, aggregate, name, :command) ||
      raise(ArgumentError, "Sub-command '#{name}' is not defined on #{context}::#{aggregate}")
  end
end

Instance Method Details

#aggregate_idString?

Returns the aggregate ID derived from the first sub-command.

Returns:

  • (String, nil)

    the aggregate ID derived from the first sub-command



92
93
94
# File 'lib/yes/core/commands/command_group.rb', line 92

def aggregate_id
  commands.first&.aggregate_id
end

#to_hHash

Returns hash form for serialization, merging normalized payload and reserved keys (matches legacy Group#to_h).

Returns:

  • (Hash)

    hash form for serialization, merging normalized payload and reserved keys (matches legacy Group#to_h)



114
115
116
117
# File 'lib/yes/core/commands/command_group.rb', line 114

def to_h
  merged = normalized_payload.merge(group_attributes.to_h)
  transaction ? merged.merge(transaction:) : merged
end