From 77cd2e18805db92146442cb2553caa02e435e792 Mon Sep 17 00:00:00 2001 From: Sascha Karnatz <68833+kulturbande@users.noreply.github.com> Date: Sat, 24 Jan 2026 15:24:52 +0100 Subject: [PATCH] Only subscribe to Rails.error if enabled The previous behavior could lead to strange errors if solid_errors is not configured in the given environment. The error reporter would try to write to solid_errors table, but the table is not available in the default database. With that if statement in place, the subscriber will only be added, if solid_errors is enabled for the environment. --- README.md | 14 ++++++++- lib/solid_errors.rb | 1 + lib/solid_errors/engine.rb | 2 +- test/engine_test.rb | 64 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 test/engine_test.rb diff --git a/README.md b/README.md index 874a177..1cedce4 100644 --- a/README.md +++ b/README.md @@ -153,8 +153,9 @@ end ### Configuration -You can configure Solid Errors via the Rails configuration object, under the `solid_errors` key. Currently, 6 configuration options are available: +You can configure Solid Errors via the Rails configuration object, under the `solid_errors` key. Currently, the following configuration options are available: +* `enabled` - Enable or disable error tracking. Defaults to `true`. See [Disabling error tracking](#disabling-error-tracking) for more information. * `connects_to` - The database configuration to use for the Solid Errors database. See [Database Configuration](#database-configuration) for more information. * `username` - The username to use for HTTP authentication. See [Authentication](#authentication) for more information. * `password` - The password to use for HTTP authentication. See [Authentication](#authentication) for more information. @@ -191,6 +192,17 @@ Running Solid Errors in a separate database is recommended, but it's also possib You won't have multiple databases, so `database.yml` doesn't need to have the errors database configuration. +#### Disabling error tracking + +Solid Errors is enabled by default. If you want to disable error tracking in a specific environment, you can set `enabled` to `false`: + +```ruby +# config/environments/development.rb +config.solid_errors.enabled = false +``` + +When disabled, Solid Errors will not subscribe to the Rails error reporter and no errors will be recorded. + #### Authentication Solid Errors does not restrict access out of the box. You must secure the dashboard yourself. However, it does provide basic HTTP authentication that can be used with basic authentication or Devise. All you need to do is setup a username and password. diff --git a/lib/solid_errors.rb b/lib/solid_errors.rb index c2a3788..cf6d35f 100644 --- a/lib/solid_errors.rb +++ b/lib/solid_errors.rb @@ -6,6 +6,7 @@ require_relative "solid_errors/engine" module SolidErrors + mattr_accessor :enabled, default: true mattr_accessor :connects_to mattr_accessor :base_controller_class, default: "::ActionController::Base" mattr_writer :username diff --git a/lib/solid_errors/engine.rb b/lib/solid_errors/engine.rb index 1a92aa5..14f8e53 100644 --- a/lib/solid_errors/engine.rb +++ b/lib/solid_errors/engine.rb @@ -18,7 +18,7 @@ class Engine < ::Rails::Engine end initializer "solid_errors.active_record.error_subscriber" do - Rails.error.subscribe(SolidErrors::Subscriber.new) + Rails.error.subscribe(SolidErrors::Subscriber.new) if SolidErrors.enabled end end end diff --git a/test/engine_test.rb b/test/engine_test.rb new file mode 100644 index 0000000..7e427d5 --- /dev/null +++ b/test/engine_test.rb @@ -0,0 +1,64 @@ +# frozen_string_literal: true + +require "test_helper" + +class EngineTest < Minitest::Test + def setup + @config = Rails.application.config + @original_config_enabled = @config.solid_errors.enabled + @original_module_enabled = SolidErrors.enabled + @subscriber = nil + + # Unsubscribe any existing SolidErrors subscribers from boot + unsubscribe_all_solid_errors_subscribers + end + + def teardown + Rails.error.unsubscribe(@subscriber) if @subscriber + @config.solid_errors.enabled = @original_config_enabled + SolidErrors.enabled = @original_module_enabled + + # Re-register subscriber if it was originally enabled + if @original_module_enabled + Rails.error.subscribe(SolidErrors::Subscriber.new) + end + end + + def test_subscriber_is_enabled_when_enabled_is_true + @config.solid_errors.enabled = true + + run_subscriber_initializer + + assert solid_errors_subscriber, "Subscriber should be registered when enabled is true" + end + + def test_subscriber_is_disabled_when_enabled_is_false + @config.solid_errors.enabled = false + + run_subscriber_initializer + + refute solid_errors_subscriber, "Subscriber should not be registered when enabled is false" + end + + private + + def run_subscriber_initializer + config_initializer = SolidErrors::Engine.initializers.find { |i| i.name == "solid_errors.config" } + SolidErrors::Engine.instance_exec(Rails.application, &config_initializer.block) + + subscriber_initializer = SolidErrors::Engine.initializers.find { |i| i.name == "solid_errors.active_record.error_subscriber" } + SolidErrors::Engine.instance_exec(Rails.application, &subscriber_initializer.block) + end + + def solid_errors_subscriber + subscribers = Rails.error.instance_variable_get(:@subscribers) + @subscriber = subscribers.find { |s| s.is_a?(SolidErrors::Subscriber) } + end + + def unsubscribe_all_solid_errors_subscribers + subscribers = Rails.error.instance_variable_get(:@subscribers) + subscribers.select { |s| s.is_a?(SolidErrors::Subscriber) }.each do |s| + Rails.error.unsubscribe(s) + end + end +end