Module: Axn::Mountable::MountingStrategies::Base

Included in:
Axn, Method, Step
Defined in:
lib/axn/mountable/mounting_strategies/_base.rb

Overview

Base module for all attachment strategies

Instance Method Summary collapse

Instance Method Details

#_should_raise_method_collision_error?(target, method_name) ⇒ Boolean

Check if we should raise an error for method collision Returns true if method exists AND target is not overriding a parent’s method (same-class collision)

Returns:

  • (Boolean)


75
76
77
78
79
80
81
82
83
# File 'lib/axn/mountable/mounting_strategies/_base.rb', line 75

def _should_raise_method_collision_error?(target, method_name)
  return false unless target.respond_to?(method_name)

  # Check if this is an inheritance override by seeing if the parent has the same method
  is_inheritance_override = target.superclass&.respond_to?(method_name)

  # Only raise error if it's a same-class collision (not inheritance override)
  !is_inheritance_override
end

#default_inherit_modeObject

Raises:

  • (ArgumentError)


15
# File 'lib/axn/mountable/mounting_strategies/_base.rb', line 15

def default_inherit_mode = raise ArgumentError, "Strategy modules must implement default_inherit_mode"

#define_namespace_methods(descriptor:, target:) ⇒ Object

Define namespace methods on the target’s Axns namespace This is public so it can be called from the inherited callback without re-registering the constant (which is already created by mounted_axn_for)



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/axn/mountable/mounting_strategies/_base.rb', line 51

def define_namespace_methods(descriptor:, target:)
  namespace = Helpers::NamespaceManager.get_or_create_namespace(target)
  name = descriptor.name
  descriptor_ref = descriptor

  # Mount methods that delegate to the cached action
  namespace.define_singleton_method(name) do |**kwargs|
    axn = descriptor_ref.mounted_axn_for(target:)
    axn.call(**kwargs)
  end

  namespace.define_singleton_method("#{name}!") do |**kwargs|
    axn = descriptor_ref.mounted_axn_for(target:)
    axn.call!(**kwargs)
  end

  namespace.define_singleton_method("#{name}_async") do |**kwargs|
    axn = descriptor_ref.mounted_axn_for(target:)
    axn.call_async(**kwargs)
  end
end

#keyObject



26
# File 'lib/axn/mountable/mounting_strategies/_base.rb', line 26

def key = name.split("::").last.underscore.to_sym

#mount(descriptor:, target:) ⇒ Object

The actual per-strategy mounting logic



18
19
20
21
# File 'lib/axn/mountable/mounting_strategies/_base.rb', line 18

def mount(descriptor:, target:)
  mount_to_namespace(descriptor:, target:)
  mount_to_target(descriptor:, target:)
end

#mount_method(target:, method_name:) ⇒ Object

Helper method to define a method on target with collision checking



29
30
31
32
33
34
35
36
37
38
# File 'lib/axn/mountable/mounting_strategies/_base.rb', line 29

def mount_method(target:, method_name:, &)
  # Check if method collision should raise an error
  # We allow overriding if this is a child class with a parent that has axn methods (inheritance scenario)
  # Otherwise, we raise an error for same-class method collisions
  if _should_raise_method_collision_error?(target, method_name)
    raise MountingError, "#{name.split('::').last} unable to attach -- method '#{method_name}' is already taken"
  end

  target.define_singleton_method(method_name, &)
end

#mount_to_namespace(descriptor:, target:) ⇒ Object

Mount methods to the namespace and register the action class



41
42
43
44
45
46
# File 'lib/axn/mountable/mounting_strategies/_base.rb', line 41

def mount_to_namespace(descriptor:, target:)
  define_namespace_methods(descriptor:, target:)
  # Register the action class as a constant in the namespace
  action_class_builder = Helpers::ClassBuilder.new(descriptor)
  action_class_builder.mount(target, descriptor.name.to_s)
end

#mount_to_target(descriptor:, target:) ⇒ Object

Mount methods directly to the target class

Raises:

  • (NotImplementedError)


24
# File 'lib/axn/mountable/mounting_strategies/_base.rb', line 24

def mount_to_target(descriptor:, target:) = raise NotImplementedError, "Strategy modules must implement mount_to_target"

#preprocess_kwargs(**kwargs) ⇒ Object

Hooks for strategy modules to configure themselves



12
# File 'lib/axn/mountable/mounting_strategies/_base.rb', line 12

def preprocess_kwargs(**kwargs) = kwargs

#strategy_specific_kwargsObject



13
# File 'lib/axn/mountable/mounting_strategies/_base.rb', line 13

def strategy_specific_kwargs = [:inherit]