Skip to content

Commit 51c45d3

Browse files
committed
Refactor ActiveRecord::QueryLogs context API
This remove the null object as discussed in rails@8af7870. Since it pretends to be nil but acts as thruthy in boolean context it cause more confusion than it clean code. `update_context` is removed in favor of `set_context` without a block.
1 parent aa0c418 commit 51c45d3

File tree

5 files changed

+32
-46
lines changed

5 files changed

+32
-46
lines changed

actionpack/lib/action_controller/railtie.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,9 @@ class Railtie < Rails::Railtie # :nodoc:
119119

120120
ActiveSupport.on_load(:active_record) do
121121
ActiveRecord::QueryLogs.taggings.merge!(
122-
controller: ->(context) { context[:controller].controller_name },
123-
action: ->(context) { context[:controller].action_name },
124-
namespaced_controller: ->(context) { context[:controller].class.name }
122+
controller: ->(context) { context[:controller]&.controller_name },
123+
action: ->(context) { context[:controller]&.action_name },
124+
namespaced_controller: ->(context) { context[:controller].class.name if context[:controller] }
125125
)
126126
end
127127
end

activejob/lib/active_job/railtie.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ class Railtie < Rails::Railtie # :nodoc:
7070
end
7171

7272
ActiveSupport.on_load(:active_record) do
73-
ActiveRecord::QueryLogs.taggings[:job] = ->(context) { context[:job].class.name unless context[:job].nil? }
73+
ActiveRecord::QueryLogs.taggings[:job] = ->(context) { context[:job].class.name if context[:job] }
7474
end
7575
end
7676
end

activerecord/lib/active_record/query_logs.rb

Lines changed: 20 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -38,24 +38,24 @@ module ActiveRecord
3838
# tags = [
3939
# :application,
4040
# {
41-
# custom_tag: ->(context) { context[:controller].controller_name },
41+
# custom_tag: ->(context) { context[:controller]&.controller_name },
4242
# custom_value: -> { Custom.value },
4343
# }
4444
# ]
4545
# ActiveRecord::QueryLogs.tags = tags
4646
#
47-
# The QueryLogs +context+ can be manipulated via +update_context+ & +set_context+ methods.
48-
#
49-
# Direct updates to a context value:
50-
#
51-
# ActiveRecord::QueryLogs.update_context(foo: Bar.new)
47+
# The QueryLogs +context+ can be manipulated via the +set_context+ method.
5248
#
5349
# Temporary updates limited to the execution of a block:
5450
#
5551
# ActiveRecord::QueryLogs.set_context(foo: Bar.new) do
5652
# posts = Post.all
5753
# end
5854
#
55+
# Direct updates to a context value:
56+
#
57+
# ActiveRecord::QueryLogs.set_context(foo: Bar.new)
58+
#
5959
# Tag comments can be prepended to the query:
6060
#
6161
# ActiveRecord::QueryLogs.prepend_comment = true
@@ -75,39 +75,25 @@ module QueryLogs
7575
mattr_accessor :cache_query_log_tags, instance_accessor: false, default: false
7676
thread_mattr_accessor :cached_comment, instance_accessor: false
7777

78-
class NullObject # :nodoc:
79-
def method_missing(method, *args, &block)
80-
NullObject.new
81-
end
82-
83-
def nil?
84-
true
85-
end
86-
87-
private
88-
def respond_to_missing?(method, include_private = false)
89-
true
90-
end
91-
end
92-
9378
class << self
9479
# Updates the context used to construct tags in the SQL comment.
95-
# Resets the cached comment if <tt>cache_query_log_tags</tt> is +true+.
96-
def update_context(**options)
97-
context.merge!(**options.symbolize_keys)
98-
self.cached_comment = nil
99-
end
100-
101-
# Updates the context used to construct tags in the SQL comment during
102-
# execution of the provided block. Resets the provided keys to their
80+
# If a block is given, it resets the provided keys to their
10381
# previous value once the block exits.
10482
def set_context(**options)
83+
options.symbolize_keys!
84+
10585
keys = options.keys
10686
previous_context = keys.zip(context.values_at(*keys)).to_h
107-
update_context(**options)
108-
yield if block_given?
109-
ensure
110-
update_context(**previous_context)
87+
context.merge!(options)
88+
self.cached_comment = nil
89+
if block_given?
90+
begin
91+
yield
92+
ensure
93+
context.merge!(previous_context)
94+
self.cached_comment = nil
95+
end
96+
end
11197
end
11298

11399
# Temporarily tag any query executed within `&block`. Can be nested.
@@ -168,7 +154,7 @@ def inline_tags
168154
end
169155

170156
def context
171-
Thread.current[:active_record_query_log_tags_context] ||= Hash.new { NullObject.new }
157+
Thread.current[:active_record_query_log_tags_context] ||= {}
172158
end
173159

174160
def escape_sql_comment(content)

activerecord/test/cases/query_logs_test.rb

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -112,12 +112,12 @@ def test_retrieves_comment_from_cache_when_enabled_and_set
112112

113113
def test_resets_cache_on_context_update
114114
ActiveRecord::QueryLogs.cache_query_log_tags = true
115-
ActiveRecord::QueryLogs.update_context(temporary: "value")
115+
ActiveRecord::QueryLogs.set_context(temporary: "value")
116116
ActiveRecord::QueryLogs.tags = [ temporary_tag: ->(context) { context[:temporary] } ]
117117

118118
assert_equal " /*temporary_tag:value*/", ActiveRecord::QueryLogs.call("")
119119

120-
ActiveRecord::QueryLogs.update_context(temporary: "new_value")
120+
ActiveRecord::QueryLogs.set_context(temporary: "new_value")
121121

122122
assert_nil ActiveRecord::QueryLogs.cached_comment
123123
assert_equal " /*temporary_tag:new_value*/", ActiveRecord::QueryLogs.call("")
@@ -128,13 +128,13 @@ def test_resets_cache_on_context_update
128128

129129
def test_ensure_context_has_symbol_keys
130130
ActiveRecord::QueryLogs.tags = [ new_key: ->(context) { context[:symbol_key] } ]
131-
ActiveRecord::QueryLogs.update_context("symbol_key" => "symbolized")
131+
ActiveRecord::QueryLogs.set_context("symbol_key" => "symbolized")
132132

133133
assert_sql(%r{/\*new_key:symbolized}) do
134134
Dashboard.first
135135
end
136136
ensure
137-
ActiveRecord::QueryLogs.update_context(application_name: nil)
137+
ActiveRecord::QueryLogs.set_context(application_name: nil)
138138
end
139139

140140
def test_default_tag_behavior
@@ -249,14 +249,14 @@ def test_multiple_custom_tags
249249

250250
def test_custom_proc_context_tags
251251
original_tags = ActiveRecord::QueryLogs.tags
252-
ActiveRecord::QueryLogs.update_context(foo: "bar")
252+
ActiveRecord::QueryLogs.set_context(foo: "bar")
253253
ActiveRecord::QueryLogs.tags = [ :application, { custom_context_proc: ->(context) { context[:foo] } } ]
254254

255255
assert_sql(%r{/\*application:active_record,custom_context_proc:bar\*/$}) do
256256
Dashboard.first
257257
end
258258
ensure
259-
ActiveRecord::QueryLogs.update_context(foo: nil)
259+
ActiveRecord::QueryLogs.set_context(foo: nil)
260260
ActiveRecord::QueryLogs.tags = original_tags
261261
end
262262

railties/test/application/query_logs_test.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ def app
123123
test "query cache is cleared between requests" do
124124
add_to_config "config.active_record.query_log_tags_enabled = true"
125125
add_to_config "config.active_record.cache_query_log_tags = true"
126-
add_to_config "config.active_record.query_log_tags = [ { dynamic: ->(context) { context[:controller].dynamic_content } } ]"
126+
add_to_config "config.active_record.query_log_tags = [ { dynamic: ->(context) { context[:controller]&.dynamic_content } } ]"
127127

128128
boot_app
129129

@@ -141,7 +141,7 @@ def app
141141
test "query cache is cleared between job executions" do
142142
add_to_config "config.active_record.query_log_tags_enabled = true"
143143
add_to_config "config.active_record.cache_query_log_tags = true"
144-
add_to_config "config.active_record.query_log_tags = [ { dynamic: ->(context) { context[:job].dynamic_content } } ]"
144+
add_to_config "config.active_record.query_log_tags = [ { dynamic: ->(context) { context[:job]&.dynamic_content } } ]"
145145

146146
boot_app
147147

0 commit comments

Comments
 (0)