Module: Charming::Controller::ClassMethods

Included in:
Charming::Controller
Defined in:
lib/charming/controller/class_methods.rb

Overview

DSL for declaring controller-level event bindings and configuration: keys, commands, timers, task handlers, the auto-rendered action, layout wrapper, and focus ring. Mixed into Controller as class methods; also exposed for tests and shared base controllers.

Instance Method Summary collapse

Instance Method Details

#auto_render(action = :show) ⇒ Object

Sets the action that the controller should auto-render after a non-rendering action runs. Defaults to :show when unset.



39
40
41
# File 'lib/charming/controller/class_methods.rb', line 39

def auto_render(action = :show)
  @auto_render_action = action.to_sym
end

#auto_render_actionObject

Returns the configured auto-render action, walking the superclass chain when undefined locally.



44
45
46
47
48
49
# File 'lib/charming/controller/class_methods.rb', line 44

def auto_render_action
  return @auto_render_action if instance_variable_defined?(:@auto_render_action)
  return superclass.auto_render_action if superclass.respond_to?(:auto_render_action)

  nil
end

#command(label, action = nil, &block) ⇒ Object

Adds a CommandPalette entry with the given label. action is a method name to send on the controller, or a block to instance_exec when selected.



21
22
23
# File 'lib/charming/controller/class_methods.rb', line 21

def command(label, action = nil, &block)
  command_bindings << Presentation::Components::CommandPalette::Command.new(label: label, value: block || action)
end

#command_bindingsObject

Array of registered command palette entries, inherited from superclass when undefined.



82
83
84
# File 'lib/charming/controller/class_methods.rb', line 82

def command_bindings
  @command_bindings ||= superclass.respond_to?(:command_bindings) ? superclass.command_bindings.dup : []
end

#focus_ring(*slots) ⇒ Object

Defines the named focus slots cycled by Tab/Shift+Tab traversal.



72
73
74
# File 'lib/charming/controller/class_methods.rb', line 72

def focus_ring(*slots)
  @focus_ring_slots = slots
end

#focus_ring_slotsObject

Returns the focus ring slots, inherited from superclass when undefined.



77
78
79
# File 'lib/charming/controller/class_methods.rb', line 77

def focus_ring_slots
  @focus_ring_slots ||= superclass.respond_to?(:focus_ring_slots) ? superclass.focus_ring_slots.dup : []
end

#key(name, action, scope: :content) ⇒ Object

Binds a key press to a controller action. name is the normalized key symbol (e.g., “up”, “q”, “ctrl+c”). scope is :content (default) for content-pane keys or :global for app-wide shortcuts that fire regardless of focus. Raises ArgumentError for any other scope.



12
13
14
15
16
17
# File 'lib/charming/controller/class_methods.rb', line 12

def key(name, action, scope: :content)
  normalized_scope = validate_key_scope(scope)
  key_name = name.to_sym
  key_bindings[key_name] = action
  key_binding_scopes[key_name] = normalized_scope
end

#key_binding_scopesObject

Hash of key scopes paralleling ‘key_bindings` (symbol key name => :content or :global).



67
68
69
# File 'lib/charming/controller/class_methods.rb', line 67

def key_binding_scopes
  @key_binding_scopes ||= superclass.respond_to?(:key_binding_scopes) ? superclass.key_binding_scopes.dup : {}
end

#key_bindingsObject

Hash of registered key bindings (symbol key name => action method name), inherited from superclass controllers.



62
63
64
# File 'lib/charming/controller/class_methods.rb', line 62

def key_bindings
  @key_bindings ||= superclass.respond_to?(:key_bindings) ? superclass.key_bindings.dup : {}
end

#layout(layout_class = :__charming_layout_reader__) ⇒ Object

Sets or returns the controller’s layout. Pass a layout class (instantiated per request), a String/Symbol template name (resolved through Presentation::Templates), or ‘false` to disable inherited layout wrapping. Called with no arguments returns the resolved layout.



54
55
56
57
58
# File 'lib/charming/controller/class_methods.rb', line 54

def layout(layout_class = :__charming_layout_reader__)
  return resolved_layout if layout_class == :__charming_layout_reader__

  @layout = layout_class
end

#on_task(name, action:) ⇒ Object

Declares a task handler for async work submitted via ‘run_task(:name)`. When the task emits a TaskEvent with the matching name, the runtime dispatches action on the controller.



33
34
35
# File 'lib/charming/controller/class_methods.rb', line 33

def on_task(name, action:)
  task_bindings[name.to_sym] = TaskBinding.new(name: name.to_sym, action: action)
end

#task_bindingsObject

Hash of task name => TaskBinding, inherited from superclass when undefined.



92
93
94
# File 'lib/charming/controller/class_methods.rb', line 92

def task_bindings
  @task_bindings ||= superclass.respond_to?(:task_bindings) ? superclass.task_bindings.dup : {}
end

#timer(name, every:, action:) ⇒ Object

Declares a timer that fires every every seconds and dispatches action on the controller. The runtime builds a TimerEvent and routes it to the active controller’s dispatch_timer.



27
28
29
# File 'lib/charming/controller/class_methods.rb', line 27

def timer(name, every:, action:)
  timer_bindings[name.to_sym] = TimerBinding.new(name: name.to_sym, interval: every, action: action)
end

#timer_bindingsObject

Hash of timer name => TimerBinding, inherited from superclass when undefined.



87
88
89
# File 'lib/charming/controller/class_methods.rb', line 87

def timer_bindings
  @timer_bindings ||= superclass.respond_to?(:timer_bindings) ? superclass.timer_bindings.dup : {}
end