Skip to content

DebugHelpers

Module providing debugging utilities for Opal applications. Outputs structured debug information to the browser console with support for grouping, timing, assertions, and more.

Usage

ruby
class MyController < StimulusController
  include OpalVite::Concerns::V1::DebugHelpers

  def connect
    debug_log("Controller connected")
    debug_stimulus_connect
  end

  def some_action
    debug_measure("Heavy Operation") do
      # ... expensive code ...
    end
  end
end

Enabling/Disabling Debug Mode

Debug output is controlled by the debug_enabled? method. There are several ways to enable debug mode:

JavaScript Global Variable

javascript
// In your main.js or HTML
window.OPAL_DEBUG = true

LocalStorage

javascript
localStorage.setItem('opal_debug', 'true')

Runtime Toggle

ruby
debug_enable!   # Enable debug mode
debug_disable!  # Disable debug mode

Basic Logging

debug_log(message, data = nil)

Log a debug message. Automatically prefixed with [DEBUG].

ruby
debug_log("User clicked button")
debug_log("Request completed", { status: 200, time: 42 })

debug_warn(message, data = nil)

Log a warning message. Automatically prefixed with [WARN].

ruby
debug_warn("Deprecated API used")
debug_warn("Slow query detected", { query: sql, time: 1500 })

debug_error(message, error = nil)

Log an error message. Always outputs regardless of debug mode.

ruby
debug_error("Failed to load data")
debug_error("API error", { code: 500, message: "Internal Server Error" })

Object Inspection

debug_inspect(obj, label = nil)

Log a Ruby object with its #inspect representation.

ruby
user = { name: "Alice", role: "admin" }
debug_inspect(user, "Current User")
# Output: [INSPECT] Current User: {:name=>"Alice", :role=>"admin"}

debug_table(data)

Display data as a table in the console. Works with arrays of hashes or single hashes.

ruby
users = [
  { name: "Alice", age: 30 },
  { name: "Bob", age: 25 }
]
debug_table(users)

Grouping

debug_group(label, &block)

Create an expandable group of debug messages.

ruby
debug_group("Request Flow") do
  debug_log("Step 1: Validate input")
  debug_log("Step 2: Process data")
  debug_log("Step 3: Send response")
end

debug_group_collapsed(label, &block)

Create a collapsed group (must click to expand).

ruby
debug_group_collapsed("Request Details") do
  debug_log("URL: /api/users")
  debug_log("Method: GET")
  debug_log("Headers: { ... }")
end

Performance Measurement

debug_time(label) / debug_time_end(label)

Start/stop a named timer.

ruby
debug_time("API Request")
# ... async operation ...
debug_time_end("API Request")
# Output: [TIMER] API Request: 245.32ms

debug_measure(label, &block)

Measure and log execution time of a block. Returns the block's result.

ruby
result = debug_measure("Heavy Calculation") do
  (1..10000).sum
end
# Output: [PERF] Heavy Calculation: 5.23ms

Assertions & Tracing

debug_assert(condition, message)

Assert a condition. Logs error if condition is false.

ruby
debug_assert(value > 0, "Value must be positive")
debug_assert(user.present?, "User is required")

debug_trace(message = nil)

Log the current call stack.

ruby
def deep_method
  debug_trace("How did we get here?")
end

Counting

debug_count(label)

Count how many times this is called with the given label.

ruby
def handle_click
  debug_count("button_clicks")
  # Output: [COUNT] button_clicks: 1
  # Next call: [COUNT] button_clicks: 2
end

debug_count_reset(label)

Reset the counter for the given label.

ruby
debug_count_reset("button_clicks")

Stimulus Integration

debug_stimulus_connect(controller = nil)

Log when a Stimulus controller connects.

ruby
def connect
  debug_stimulus_connect
  # Output: [STIMULUS] Connected: my-controller
end

debug_stimulus_disconnect(controller = nil)

Log when a Stimulus controller disconnects.

ruby
def disconnect
  debug_stimulus_disconnect
end

debug_stimulus_action(action_name, event = nil)

Log a Stimulus action execution.

ruby
def click(event)
  debug_stimulus_action("click", event)
  # Output: [STIMULUS] Action: click Event: { type: "click", ... }
end

Configuration

debug_enabled?

Check if debugging is enabled.

ruby
if debug_enabled?
  # Do expensive debug operations
end

debug_enable! / debug_disable!

Toggle debug mode at runtime. Also persists to localStorage.

ruby
debug_enable!   # Enable and persist
debug_disable!  # Disable and clear persistence

Example: Full Controller

ruby
class TodoController < StimulusController
  include OpalVite::Concerns::V1::DebugHelpers
  include OpalVite::Concerns::V1::DomHelpers

  def connect
    debug_stimulus_connect
    debug_log("Initializing todo list")
  end

  def add
    debug_group("Adding Todo") do
      debug_time("todo:add")

      title = input_value
      debug_assert(!title.empty?, "Title cannot be empty")

      debug_measure("Create Todo") do
        create_todo(title)
      end

      debug_count("todos_added")
      debug_time_end("todo:add")
    end
  end

  def disconnect
    debug_stimulus_disconnect
  end
end

Tips

  1. Use in Development Only: Debug output is disabled by default. Enable only during development.

  2. Group Related Messages: Use debug_group to organize related debug output.

  3. Measure Performance: Use debug_measure to identify slow operations.

  4. Assertions for Validation: Use debug_assert to catch bugs early.

  5. Count for Tracking: Use debug_count to track how often code paths execute.

Released under the MIT License.