Class: Railsmith::Hooks::HookChain

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/railsmith/hooks/hook_chain.rb

Overview

Immutable, ordered list of HookEntry records. Chains are cheap value objects: every “mutation” (append, filter, remove) returns a new chain, which is how class-level registries stay safe to share across requests.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(entries = []) ⇒ HookChain

Returns a new instance of HookChain.



13
14
15
16
# File 'lib/railsmith/hooks/hook_chain.rb', line 13

def initialize(entries = [])
  @entries = entries.dup.freeze
  freeze
end

Instance Attribute Details

#entriesObject (readonly)

Returns the value of attribute entries.



11
12
13
# File 'lib/railsmith/hooks/hook_chain.rb', line 11

def entries
  @entries
end

Instance Method Details

#append(entry) ⇒ Object

Returns a new chain with entry appended.



55
56
57
# File 'lib/railsmith/hooks/hook_chain.rb', line 55

def append(entry)
  self.class.new([*@entries, entry])
end

#concat(other) ⇒ Object

Returns a new chain with every entry from other appended, preserving order. Self’s entries come first (used for “global hooks wrap class hooks” layering when called with global as the outer and class as the argument, or vice versa).



62
63
64
65
66
# File 'lib/railsmith/hooks/hook_chain.rb', line 62

def concat(other)
  return self if other.nil? || other.empty?

  self.class.new([*@entries, *other.entries])
end

#eachObject



18
19
20
# File 'lib/railsmith/hooks/hook_chain.rb', line 18

def each(&)
  @entries.each(&)
end

#empty?Boolean

Returns:

  • (Boolean)


22
23
24
# File 'lib/railsmith/hooks/hook_chain.rb', line 22

def empty?
  @entries.empty?
end

#for_action(action) ⇒ Object

Returns a new chain containing only entries that target action.



31
32
33
34
# File 'lib/railsmith/hooks/hook_chain.rb', line 31

def for_action(action)
  action_sym = action.to_sym
  self.class.new(@entries.select { |e| e.applies_to?(action_sym) })
end

#for_domain(domain_key) ⇒ Object

Returns a new chain filtered to entries whose domain scope matches domain_key. Entries without a domain scope (class-level hooks) always pass.



43
44
45
# File 'lib/railsmith/hooks/hook_chain.rb', line 43

def for_domain(domain_key)
  self.class.new(@entries.select { |e| e.matches_domain?(domain_key) })
end

#of_type(type) ⇒ Object

Returns a new chain containing only entries of type (:before/:after/:around).



37
38
39
# File 'lib/railsmith/hooks/hook_chain.rb', line 37

def of_type(type)
  self.class.new(@entries.select { |e| e.type == type })
end

#sizeObject



26
27
28
# File 'lib/railsmith/hooks/hook_chain.rb', line 26

def size
  @entries.size
end

#without(hook_name, type: nil) ⇒ Object

Returns a new chain with every entry named hook_name removed. Optionally restrict removal to a specific hook type.



49
50
51
52
# File 'lib/railsmith/hooks/hook_chain.rb', line 49

def without(hook_name, type: nil)
  target = hook_name.to_sym
  self.class.new(@entries.reject { |e| e.name == target && (type.nil? || e.type == type) })
end