/
record_fetch_warning.rb
49 lines (42 loc) · 1.6 KB
/
record_fetch_warning.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# frozen_string_literal: true
module ActiveRecord
class Relation
module RecordFetchWarning
# When this module is prepended to ActiveRecord::Relation and
# +config.active_record.warn_on_records_fetched_greater_than+ is
# set to an integer, if the number of records a query returns is
# greater than the value of +warn_on_records_fetched_greater_than+,
# a warning is logged. This allows for the detection of queries that
# return a large number of records, which could cause memory bloat.
#
# In most cases, fetching large number of records can be performed
# efficiently using the ActiveRecord::Batches methods.
# See ActiveRecord::Batches for more information.
def exec_queries
QueryRegistry.reset
super.tap do |records|
if logger && ActiveRecord.warn_on_records_fetched_greater_than
if records.length > ActiveRecord.warn_on_records_fetched_greater_than
logger.warn "Query fetched #{records.size} #{@klass} records: #{QueryRegistry.queries.join(";")}"
end
end
end
end
# :stopdoc:
ActiveSupport::Notifications.subscribe("sql.active_record") do |*, payload|
QueryRegistry.queries << payload[:sql]
end
# :startdoc:
module QueryRegistry # :nodoc:
extend self
def queries
ActiveSupport::IsolatedExecutionState[:active_record_query_registry] ||= []
end
def reset
queries.clear
end
end
end
end
end
ActiveRecord::Relation.prepend ActiveRecord::Relation::RecordFetchWarning