Class: RSpecTracer::Rails::Notifications Private
- Inherits:
-
Object
- Object
- RSpecTracer::Rails::Notifications
- Defined in:
- lib/rspec_tracer/rails/notifications.rb
Overview
This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.
ActiveSupport::Notifications observer for Rails-side inputs that Coverage and IOHooks can’t see directly. Subscribes to:
- render_template.action_view -> :template
- render_partial.action_view -> :template
- render_collection.action_view -> :template (Rails 7.1+)
- sql.active_record -> :notification
(on the first query per example, emits db/schema.rb +
db/structure.sql as inputs)
Lifecycle mirrors IOHooks: Engine.setup installs, example_started opens a thread-local bucket, subscribers append, example_finished harvests and clears the bucket, Engine.finalize unsubscribes.
Payload access is defensively permissive - Rails minors differ on symbol vs string keys; missing payload or nil identifier is swallowed. Errors inside subscribers never propagate (CLAUDE.md “graceful degradation”).
Precedence: an observed template path already covered by a user declared glob (e.g. the Preset :views glob) skips notification emission via the injected ‘filter:` callable. Matches IOHooks’ declared-glob-precedence rule from ARCHITECTURE.md.
The sql.active_record subscriber is only attached when the caller passes a non-empty ‘ar_schema_paths:` list. Engine resolves the list from the `track_ar_schema_notifications` opt-in DSL; absent that, the AR subscriber is never installed and the sql.active_record event stream is ignored.
Constant Summary collapse
- BUCKET_KEY =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Internal constant.
:rspec_tracer_rails_bucket- AR_FLAG_KEY =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Internal constant.
:rspec_tracer_rails_ar_emitted
Class Attribute Summary collapse
-
.root ⇒ Object
readonly
private
Internal attribute.
Class Method Summary collapse
-
.clear_bucket ⇒ Object
private
rubocop:enable Naming/AccessorMethodName.
-
.current_bucket ⇒ Object
private
Internal method on the tracer pipeline.
-
.handle_render_event(payload) ⇒ Object
private
Pure-logic entry point for the render_*.action_view subscribers.
-
.handle_sql_event(_payload) ⇒ Object
private
Pure-logic entry point for the sql.active_record subscriber.
-
.install(root:, filter: ->(_path) { true }, ar_schema_paths: []) ⇒ Object
private
Internal method on the tracer pipeline.
-
.installed? ⇒ Boolean
private
Internal method on the tracer pipeline.
-
.record_ar_schema ⇒ Object
private
Emit the pre-digested schema Inputs into the bucket on the first sql.active_record event per example.
-
.record_template(path) ⇒ Object
private
Record a :template Input for the observed render identifier.
-
.set_bucket(bucket) ⇒ Object
private
rubocop:disable Naming/AccessorMethodName.
-
.uninstall ⇒ Object
private
Internal method on the tracer pipeline.
Class Attribute Details
.root ⇒ Object (readonly)
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Internal attribute.
50 51 52 |
# File 'lib/rspec_tracer/rails/notifications.rb', line 50 def root @root end |
Class Method Details
.clear_bucket ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
rubocop:enable Naming/AccessorMethodName
94 95 96 97 |
# File 'lib/rspec_tracer/rails/notifications.rb', line 94 def clear_bucket Thread.current[BUCKET_KEY] = nil Thread.current[AR_FLAG_KEY] = nil end |
.current_bucket ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Internal method on the tracer pipeline.
101 102 103 |
# File 'lib/rspec_tracer/rails/notifications.rb', line 101 def current_bucket Thread.current[BUCKET_KEY] end |
.handle_render_event(payload) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Pure-logic entry point for the render_*.action_view subscribers. Extracted so mutation smoke can exercise payload parsing without driving AS::Notifications.
108 109 110 111 112 113 114 115 |
# File 'lib/rspec_tracer/rails/notifications.rb', line 108 def handle_render_event(payload) return nil unless payload.is_a?(Hash) identifier = payload[:identifier] || payload['identifier'] return nil if identifier.nil? record_template(identifier) end |
.handle_sql_event(_payload) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Pure-logic entry point for the sql.active_record subscriber. Payload contents are ignored - the event itself is the “this example touched AR” signal.
120 121 122 |
# File 'lib/rspec_tracer/rails/notifications.rb', line 120 def handle_sql_event(_payload) record_ar_schema end |
.install(root:, filter: ->(_path) { true }, ar_schema_paths: []) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Internal method on the tracer pipeline.
54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/rspec_tracer/rails/notifications.rb', line 54 def install(root:, filter: ->(_path) { true }, ar_schema_paths: []) @root = File.(root) @root_prefix = "#{@root}/" @filter = filter @ar_schema_inputs = build_schema_inputs(ar_schema_paths) @handles = [] subscribe_render_template subscribe_render_partial subscribe_render_collection if render_collection_supported? subscribe_sql_active_record if ar_enabled? self end |
.installed? ⇒ Boolean
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Internal method on the tracer pipeline.
83 84 85 |
# File 'lib/rspec_tracer/rails/notifications.rb', line 83 def installed? !@root_prefix.nil? end |
.record_ar_schema ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Emit the pre-digested schema Inputs into the bucket on the first sql.active_record event per example. Subsequent events short-circuit via AR_FLAG_KEY - O(1) after the first query.
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/rspec_tracer/rails/notifications.rb', line 158 def record_ar_schema return nil if @ar_schema_inputs.nil? || @ar_schema_inputs.empty? bucket = Thread.current[BUCKET_KEY] return nil if bucket.nil? return nil if Thread.current[AR_FLAG_KEY] Thread.current[AR_FLAG_KEY] = true @ar_schema_inputs.each do |input| bucket[input.identity] ||= input end nil rescue StandardError nil end |
.record_template(path) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Record a :template Input for the observed render identifier. Guarded by the same fast-reject ladder as IOHooks: install state, bucket presence, path-under-root, filter callable, identity dedup. The early-return ladder looks complex to rubocop’s metric but is the simplest shape for a hot path. rubocop:disable Metrics/PerceivedComplexity
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/rspec_tracer/rails/notifications.rb', line 130 def record_template(path) return nil if @root_prefix.nil? bucket = Thread.current[BUCKET_KEY] return nil if bucket.nil? return nil unless path.is_a?(String) || path.respond_to?(:to_s) path_str = path.to_s return nil unless path_str.start_with?(@root_prefix) return nil unless @filter.call(path_str) identity = "template:#{path_str[@root_prefix.length..]}" return nil if bucket.key?(identity) digest = Tracker::FileDigest.compute(path_str) return nil if digest.nil? bucket[identity] = Tracker::Input.for_file( path: path_str, kind: :template, digest: digest, root: @root ) rescue StandardError nil end |
.set_bucket(bucket) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
rubocop:disable Naming/AccessorMethodName
88 89 90 91 |
# File 'lib/rspec_tracer/rails/notifications.rb', line 88 def set_bucket(bucket) Thread.current[BUCKET_KEY] = bucket Thread.current[AR_FLAG_KEY] = false end |
.uninstall ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Internal method on the tracer pipeline.
71 72 73 74 75 76 77 78 79 |
# File 'lib/rspec_tracer/rails/notifications.rb', line 71 def uninstall (@handles || []).each { |handle| safely_unsubscribe(handle) } @handles = nil @root = nil @root_prefix = nil @filter = nil @ar_schema_inputs = nil self end |