### Install Hooks Gem Source: https://github.com/apotonick/hooks/blob/master/README.md Add the 'hooks' gem to your Gemfile for use in your Ruby project. ```ruby gem "hooks" ``` -------------------------------- ### Execute Instance Hook Callback Chain with `run_hook` Source: https://context7.com/apotonick/hooks/llms.txt Run all registered callbacks for a hook on the calling instance. Additional arguments are passed to each callback. Returns a `Results` array. ```ruby class FileProcessor include Hooks define_hook :after_process after_process :compress after_process :checksum after_process { |file| "logged:#{file}" } def compress(file); "compressed:#{file}"; end def checksum(file); "sha256:abc123"; end end processor = FileProcessor.new results = processor.run_hook(:after_process, "report.csv") puts results.inspect # => ["compressed:report.csv", "sha256:abc123", "logged:report.csv"] puts results.halted? # => false puts results.not_halted? # => true ``` -------------------------------- ### Define Instance Hooks Source: https://github.com/apotonick/hooks/blob/master/README.md Include `Hooks::InstanceHooks` to define hooks and add callbacks on a per-instance basis. ```ruby class Cat include Hooks include Hooks::InstanceHooks define_hook :after_dark after_dark { "Chase mice" } end ``` -------------------------------- ### Run Hooks and Execute Callbacks Source: https://github.com/apotonick/hooks/blob/master/README.md Invoke a hook using `run_hook` to execute all associated callbacks. Callbacks run in the instance's context. ```ruby cat.run_hook :after_dinner # => Ice cream for #! Hell, yeah! ``` -------------------------------- ### Per-Instance Hooks with Hooks::InstanceHooks Source: https://context7.com/apotonick/hooks/llms.txt Include `Hooks::InstanceHooks` to give each object its own isolated hook store. Instances can define and run hooks independently. ```ruby class Worker include Hooks include Hooks::InstanceHooks define_hook :on_complete on_complete { "class-level callback" } end w1 = Worker.new w2 = Worker.new # Instance-specific callback — only w1 runs it w1.on_complete { "w1 exclusive" } r1 = w1.run_hook(:on_complete) r2 = w2.run_hook(:on_complete) puts r1.inspect # => ["class-level callback", "w1 exclusive"] puts r2.inspect # => ["class-level callback"] # Instances can also define entirely new hooks w1.define_hook :on_retry w1.on_retry { "retrying..." } puts w1.run_hook(:on_retry).inspect # => ["retrying..."] ``` -------------------------------- ### run_hook (instance) Source: https://context7.com/apotonick/hooks/llms.txt Execute a hook's callback chain on the calling instance, forwarding arguments and collecting return values. ```APIDOC ## run_hook (instance) ### Description Runs all callbacks registered for the named hook on the calling instance. Additional arguments are forwarded to every callback. Returns a `Hooks::Hook::Results` array containing each callback's return value. ### Usage ```ruby class FileProcessor include Hooks define_hook :after_process after_process :compress after_process :checksum after_process { |file| "logged:#{file}" } def compress(file); "compressed:#{file}"; end def checksum(file); "sha256:abc123"; end end processor = FileProcessor.new results = processor.run_hook(:after_process, "report.csv") puts results.inspect # => ["compressed:report.csv", "sha256:abc123", "logged:report.csv"] puts results.halted? # => false puts results.not_halted? # => true ``` ``` -------------------------------- ### Include Hooks in a Class Source: https://context7.com/apotonick/hooks/llms.txt Include the `Hooks` module to add hook definition and callback registration capabilities to a class. Callbacks are executed in the instance context. ```ruby require 'hooks' class Publisher include Hooks define_hooks :before_publish, :after_publish before_publish :validate_content after_publish :notify_subscribers after_publish { puts "Published at #{Time.now}" } def validate_content puts "Validating..." end def notify_subscribers puts "Notifying subscribers..." end end pub = Publisher.new pub.run_hook(:before_publish) # => Validating... pub.run_hook(:after_publish) # => Notifying subscribers... # => Published at 2024-01-15 10:30:00 +0000 ``` -------------------------------- ### Execute Class-Level Hook with `run_hook` Source: https://context7.com/apotonick/hooks/llms.txt Execute hooks directly on the class to handle class-level lifecycle events. Callbacks are run as class methods. ```ruby class Plugin include Hooks define_hook :on_load on_load :register_defaults def self.register_defaults puts "Registering default settings..." end end Plugin.run_hook(:on_load) # => Registering default settings... ``` -------------------------------- ### Define New Hooks on Instances Source: https://github.com/apotonick/hooks/blob/master/README.md Instances can also define new hooks, similar to how classes define them. ```ruby garfield.define_hook :before_six garfield.before_six { .. } ``` -------------------------------- ### Define Hooks with `define_hook` and `define_hooks` Source: https://context7.com/apotonick/hooks/llms.txt Use `define_hook` for a single hook name or `define_hooks` for multiple names to register hooks on a class. This generates writer methods for adding callbacks. ```ruby class Order include Hooks # Single hook define_hook :after_payment # Multiple hooks at once define_hooks :before_ship, :after_ship, :on_cancel end Order.after_payment :send_receipt Order.before_ship :reserve_stock Order.after_ship { puts "Shipped!" } order = Order.new results = order.run_hook(:after_ship) # => Shipped! puts results # => ["Shipped!"] (array of return values) puts results.halted? # => false ``` -------------------------------- ### Collect Results from Callbacks Source: https://github.com/apotonick/hooks/blob/master/README.md The `run_hook` method returns an array of results from each executed callback. ```ruby class Garfield include Hooks define_hook :after_dark after_dark { "Chase mice" } after_dark { "Enjoy supper" } end Garfield.new.run_hook :after_dark # => ["Chase mice", "Enjoy supper"] ``` -------------------------------- ### Register Callbacks using Hook Writer Methods Source: https://context7.com/apotonick/hooks/llms.txt Register callbacks using the generated writer methods for each hook. Callbacks can be method symbols or blocks and are inherited by subclasses. ```ruby class Workflow include Hooks define_hook :on_transition on_transition :log_transition on_transition :audit_trail on_transition { |context, event| puts "Transitioned via #{event}" } def log_transition(context, event) puts "LOG: #{event}" end def audit_trail(context, event) puts "AUDIT: #{event} at #{Time.now}" end end wf = Workflow.new wf.run_hook(:on_transition, wf, :approve) # => LOG: approve # => AUDIT: approve at 2024-01-15 10:30:00 +0000 # => Transitioned via approve ``` -------------------------------- ### include Hooks Source: https://context7.com/apotonick/hooks/llms.txt Including the `Hooks` module in a class makes hook definition and callback registration methods available. ```APIDOC ## include Hooks ### Description Including `Hooks` in a class extends it with `ClassMethods` and sets up an inheritable `_hooks` store. All hook-definition and callback-registration methods become available immediately. ### Usage ```ruby require 'hooks' class Publisher include Hooks define_hooks :before_publish, :after_publish before_publish :validate_content after_publish :notify_subscribers after_publish { puts "Published at #{Time.now}" } def validate_content puts "Validating..." end def notify_subscribers puts "Notifying subscribers..." end end pub = Publisher.new pub.run_hook(:before_publish) # => Validating... pub.run_hook(:after_publish) # => Notifying subscribers... # => Published at 2024-01-15 10:30:00 +0000 ``` ``` -------------------------------- ### run_hook (class-level) Source: https://context7.com/apotonick/hooks/llms.txt Execute hooks in a class context, useful for class-level lifecycle events. ```APIDOC ## run_hook (class-level) ### Description Calling `run_hook` directly on the class runs callbacks as class methods. Useful for class-level lifecycle events (e.g., loading, configuration). ### Usage ```ruby class Plugin include Hooks define_hook :on_load on_load :register_defaults def self.register_defaults puts "Registering default settings..." end end Plugin.run_hook(:on_load) # => Registering default settings... ``` ``` -------------------------------- ### Pass Arguments to Callbacks Source: https://github.com/apotonick/hooks/blob/master/README.md Arguments can be passed to `run_hook` and will be forwarded to the callback methods or blocks. ```ruby cat.run_hook :before_dinner, cat, Time.now ``` -------------------------------- ### Execute Callback in Original Context Source: https://github.com/apotonick/hooks/blob/master/README.md Returning `nil` from the `:scope` lambda executes the callback in the original context. ```ruby define_hook :before_lunch, scope: lambda { |*| nil } what = "hands" before_lunch << lambda { puts "wash #{what}" } # executed in original context. ``` -------------------------------- ### Add Callbacks to Hooks Source: https://github.com/apotonick/hooks/blob/master/README.md Callbacks can be added as methods or blocks to defined hooks. Blocks are executed with instance context. ```ruby before_dinner :wash_paws after_dinner do puts "Ice cream for #{self}!" end after_dinner :have_a_dessert # => refers to Cat#have_a_dessert def have_a_dessert puts "Hell, yeah!" end ``` -------------------------------- ### define_hook / define_hooks Source: https://context7.com/apotonick/hooks/llms.txt Declare one or more named hooks on a class, generating a writer method for each to register callbacks. ```APIDOC ## define_hook / define_hooks ### Description Registers one or more hook names on the class and compiles a writer method for each (e.g., `define_hook :after_save` generates an `after_save` class method for adding callbacks). Accepts an options hash as the last argument. ### Usage ```ruby class Order include Hooks # Single hook define_hook :after_payment # Multiple hooks at once define_hooks :before_ship, :after_ship, :on_cancel end Order.after_payment :send_receipt Order.before_ship :reserve_stock Order.after_ship { puts "Shipped!" } order = Order.new results = order.run_hook(:after_ship) # => Shipped! puts results # => ["Shipped!"] (array of return values) puts results.halted? # => false ``` ``` -------------------------------- ### Define Callbacks Accepting Arguments Source: https://github.com/apotonick/hooks/blob/master/README.md Callbacks can be defined to accept parameters passed during hook invocation. ```ruby before_dinner :wash_pawns before_dinner do |who, when| ... end def wash_pawns(who, when) ``` -------------------------------- ### Add Instance-Specific Callbacks Source: https://github.com/apotonick/hooks/blob/master/README.md Instances can add their own callbacks to inherited hooks without affecting the class definition. ```ruby garfield = Cat.new garfield.after_dark :sleep garfield.run_hook(:after_dark) # => invoke "Chase mice" hook and #sleep ``` -------------------------------- ### writer method Source: https://context7.com/apotonick/hooks/llms.txt Register callbacks for a defined hook using a symbol (method name) or a block. ```APIDOC ## writer method ### Description Each defined hook generates a class-level writer method accepting either a symbol (method name) or a block. Callbacks are appended in order and inherited by subclasses. ### Usage ```ruby class Workflow include Hooks define_hook :on_transition on_transition :log_transition on_transition :audit_trail on_transition { |context, event| puts "Transitioned via #{event}" } def log_transition(context, event) puts "LOG: #{event}" end def audit_trail(context, event) puts "AUDIT: #{event} at #{Time.now}" end end wf = Workflow.new wf.run_hook(:on_transition, wf, :approve) # => LOG: approve # => AUDIT: approve at 2024-01-15 10:30:00 +0000 # => Transitioned via approve ``` ``` -------------------------------- ### Inheritance of Hooks and Callbacks Source: https://github.com/apotonick/hooks/blob/master/README.md Hooks and their callbacks are inherited by subclasses. Callbacks are invoked in the order they are inherited. ```ruby class Garfield < Cat after_dinner :want_some_more def want_some_more puts "Is that all?" end end Garfield.new.run_hook :after_dinner # => Ice cream for #! Hell, yeah! Is that all? ``` -------------------------------- ### Define Hook with scope: lambda Source: https://context7.com/apotonick/hooks/llms.txt The `scope:` option allows custom callback execution contexts. A lambda returning a context object (or `nil` for original context) determines where callbacks run. ```ruby class AuditedService include Hooks # All callbacks run in the context of an AuditLogger instance define_hook :on_action, scope: lambda { |callback, scope| AuditLogger.new(scope) } on_action :record_event def record_event # `self` here is the AuditLogger instance, not AuditedService puts "Recording in: #{self.class}" end end class AuditLogger def initialize(origin); @origin = origin; end def record_event; puts "Recording in: #{self.class} (origin: #{@origin.class})"; end end AuditedService.new.run_hook(:on_action) # => Recording in: AuditLogger (origin: AuditedService) ``` -------------------------------- ### Inspect Registered Callbacks with callbacks_for_hook Source: https://context7.com/apotonick/hooks/llms.txt Use `callbacks_for_hook` to retrieve the raw list of registered callbacks for a hook. This is useful for introspection or custom callback execution. ```ruby class Pipeline include Hooks define_hook :process process :step_one process :step_two process { "inline step" } end cbs = Pipeline.callbacks_for_hook(:process) puts cbs.size # => 3 instance = Pipeline.new cbs.each do |cb| result = cb.evaluate(instance) puts result.inspect end # => nil (step_one not defined, returns nil) # => nil # => "inline step" ``` -------------------------------- ### Halt Callback Chain on Falsey Return Source: https://github.com/apotonick/hooks/blob/master/README.md Use `halts_on_falsey: true` option to stop executing callbacks if any callback returns `nil` or `false`. ```ruby class Garfield include Hooks define_hook :after_dark, halts_on_falsey: true after_dark { "Chase mice" } after_dark { nil } after_dark { "Enjoy supper" } end result = Garfield.new.run_hook :after_dark # => ["Chase mice"] ``` -------------------------------- ### Define Hooks in a Ruby Class Source: https://github.com/apotonick/hooks/blob/master/README.md Use `define_hooks` to declare hook names within a Ruby class. This sets up the hooks for adding callbacks later. ```ruby require 'hooks' class Cat include Hooks define_hooks :before_dinner, :after_dinner ``` -------------------------------- ### Define Hook with halts_on_falsey: true Source: https://context7.com/apotonick/hooks/llms.txt Use `halts_on_falsey: true` to stop callback chains when any callback returns `nil` or `false`. The results will include only successful callbacks before the halt. ```ruby class AccessControl include Hooks define_hook :before_action, halts_on_falsey: true before_action :check_authenticated before_action :check_authorized before_action :check_rate_limit # never reached if auth fails def check_authenticated; puts "Auth: ok"; true; end def check_authorized; puts "Authz: DENIED"; false; end def check_rate_limit; puts "Rate: ok"; true; end end result = AccessControl.new.run_hook(:before_action) # => Auth: ok # => Authz: DENIED puts result.inspect # => [true] puts result.halted? # => true ``` -------------------------------- ### Define Custom Execution Scope for Hooks Source: https://github.com/apotonick/hooks/blob/master/README.md The `:scope` option allows specifying a custom execution context for hook callbacks using a lambda. ```ruby define_hook :before_lunch, scope: lambda { |callback, scope| Logger } ``` -------------------------------- ### Check if Callback Chain Was Halted Source: https://github.com/apotonick/hooks/blob/master/README.md The result object from `run_hook` has a `halted?` method to check if the callback chain was terminated early. ```ruby result.halted? #=> true ``` -------------------------------- ### Hook Inheritance in Subclasses Source: https://context7.com/apotonick/hooks/llms.txt Hook definitions and callbacks are inherited by subclasses. Subclasses can add their own callbacks without affecting the parent class. ```ruby class Animal include Hooks define_hook :after_eat after_eat :digest def digest; puts "Digesting..."; end end class Cat < Animal after_eat :purr def purr; puts "Purrrr..."; end end class Kitten < Cat after_eat :nap def nap; puts "Napping..."; end end Kitten.new.run_hook(:after_eat) # => Digesting... # => Purrrr... # => Napping... # Parent class unaffected Animal.new.run_hook(:after_eat) # => Digesting... ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.