Class: AndOne::Detection
- Inherits:
-
Object
- Object
- AndOne::Detection
- Defined in:
- lib/and_one/detection.rb
Overview
Represents a single N+1 detection: the repeated queries, their call site, and metadata.
Instance Attribute Summary collapse
-
#adapter ⇒ Object
readonly
Returns the value of attribute adapter.
-
#caller_locations ⇒ Object
readonly
Returns the value of attribute caller_locations.
-
#count ⇒ Object
readonly
Returns the value of attribute count.
-
#queries ⇒ Object
readonly
Returns the value of attribute queries.
Instance Method Summary collapse
-
#fingerprint ⇒ Object
A stable fingerprint for this detection, based on the query shape and the target table.
-
#fix_location ⇒ Object
The frame where the AR relation/collection was likely loaded or iterated.
-
#initialize(queries:, caller_locations:, count:, adapter: nil) ⇒ Detection
constructor
A new instance of Detection.
-
#origin_frame ⇒ Object
The first frame in the call stack that is application code (not a gem, not ruby stdlib, not and_one itself).
-
#raw_caller_strings ⇒ Object
The raw caller strings (before backtrace cleaning).
-
#sample_query ⇒ Object
Returns the SQL of the first query as the representative example.
-
#table_name ⇒ Object
Attempt to extract the table name from the repeated query.
Constructor Details
#initialize(queries:, caller_locations:, count:, adapter: nil) ⇒ Detection
Returns a new instance of Detection.
10 11 12 13 14 15 |
# File 'lib/and_one/detection.rb', line 10 def initialize(queries:, caller_locations:, count:, adapter: nil) @queries = queries @caller_locations = caller_locations @count = count @adapter = adapter end |
Instance Attribute Details
#adapter ⇒ Object (readonly)
Returns the value of attribute adapter.
8 9 10 |
# File 'lib/and_one/detection.rb', line 8 def adapter @adapter end |
#caller_locations ⇒ Object (readonly)
Returns the value of attribute caller_locations.
8 9 10 |
# File 'lib/and_one/detection.rb', line 8 def caller_locations @caller_locations end |
#count ⇒ Object (readonly)
Returns the value of attribute count.
8 9 10 |
# File 'lib/and_one/detection.rb', line 8 def count @count end |
#queries ⇒ Object (readonly)
Returns the value of attribute queries.
8 9 10 |
# File 'lib/and_one/detection.rb', line 8 def queries @queries end |
Instance Method Details
#fingerprint ⇒ Object
A stable fingerprint for this detection, based on the query shape and
the target table. Independent of call site so the same N+1 pattern
produces the same fingerprint regardless of where it's triggered.
For location-specific ignoring, use path: rules in .and_one_ignore.
31 32 33 34 35 36 |
# File 'lib/and_one/detection.rb', line 31 def fingerprint @fingerprint ||= begin sql_fp = Fingerprint.generate(sample_query) Digest::SHA256.hexdigest("#{sql_fp}:#{table_name}")[0, 12] end end |
#fix_location ⇒ Object
The frame where the AR relation/collection was likely loaded or iterated. This is the best place to add .includes().
51 52 53 |
# File 'lib/and_one/detection.rb', line 51 def fix_location @fix_location ||= find_fix_location end |
#origin_frame ⇒ Object
The first frame in the call stack that is application code (not a gem, not ruby stdlib, not and_one itself)
45 46 47 |
# File 'lib/and_one/detection.rb', line 45 def origin_frame @origin_frame ||= find_origin_frame end |
#raw_caller_strings ⇒ Object
The raw caller strings (before backtrace cleaning)
39 40 41 |
# File 'lib/and_one/detection.rb', line 39 def raw_caller_strings @raw_caller_strings ||= caller_locations.map(&:to_s) end |
#sample_query ⇒ Object
Returns the SQL of the first query as the representative example
18 19 20 |
# File 'lib/and_one/detection.rb', line 18 def sample_query @queries.first end |
#table_name ⇒ Object
Attempt to extract the table name from the repeated query
23 24 25 |
# File 'lib/and_one/detection.rb', line 23 def table_name @table_name ||= extract_table_name(sample_query) end |