Improve taggings API by introducing a null object

Instead of adding chains of `&.` we should use a null object to allow
the taggings definition to be more concise.
This commit is contained in:
Rafael Mendonça França 2021-08-17 23:07:51 +00:00
parent 18cd634e07
commit 8af78700d2
No known key found for this signature in database
GPG Key ID: FC23B6D0F1EEE948
3 changed files with 32 additions and 11 deletions

View File

@ -101,9 +101,9 @@ module ActionController
ActiveSupport.on_load(:active_record) do
ActiveRecord::QueryLogs.taggings.merge!(
controller: -> { context[:controller]&.controller_name },
action: -> { context[:controller]&.action_name },
namespaced_controller: -> { context[:controller]&.class&.name }
controller: -> { context[:controller].controller_name },
action: -> { context[:controller].action_name },
namespaced_controller: -> { context[:controller].class.name }
)
end
end

View File

@ -58,12 +58,12 @@ module ActiveJob
if app.config.active_record.query_log_tags_enabled && app.config.active_job.log_query_tags_around_perform != false
app.config.active_record.query_log_tags << :job
ActiveSupport.on_load(:active_job) do
include ActiveJob::QueryTags
end
ActiveSupport.on_load(:active_job) do
include ActiveJob::QueryTags
end
ActiveSupport.on_load(:active_record) do
ActiveRecord::QueryLogs.taggings[:job] = -> { context[:job]&.class&.name }
ActiveSupport.on_load(:active_record) do
ActiveRecord::QueryLogs.taggings[:job] = -> { context[:job].class.name }
end
end
end

View File

@ -72,6 +72,21 @@ module ActiveRecord
mattr_accessor :cache_query_log_tags, instance_accessor: false, default: false
thread_mattr_accessor :cached_comment, instance_accessor: false
class NullObject # :nodoc:
def method_missing(method, *args, &block)
NullObject.new
end
def nil?
true
end
private
def respond_to_missing?(method, include_private = false)
true
end
end
class << self
# Updates the context used to construct tags in the SQL comment.
# Resets the cached comment if <tt>cache_query_log_tags</tt> is +true+.
@ -87,7 +102,7 @@ module ActiveRecord
update_context(**options)
yield if block_given?
ensure
update_context(**options.transform_values! { nil })
update_context(**options.transform_values! { NullObject.new })
end
# Temporarily tag any query executed within `&block`. Can be nested.
@ -139,11 +154,15 @@ module ActiveRecord
# Return the set of active inline tags from +with_tag+.
def inline_tags
context[:inline_tags] ||= []
if context[:inline_tags].nil?
context[:inline_tags] = []
else
context[:inline_tags]
end
end
def context
Thread.current[:active_record_query_log_tags_context] ||= {}
Thread.current[:active_record_query_log_tags_context] ||= Hash.new { NullObject.new }
end
def escape_sql_comment(content)
@ -153,11 +172,13 @@ module ActiveRecord
def tag_content
tags.flat_map { |i| [*i] }.filter_map do |tag|
key, value_input = tag
val = case value_input
when nil then tag_value(key) if taggings.has_key? key
when Proc then instance_exec(&value_input)
else value_input
end
"#{key}:#{val}" unless val.nil?
end.join(",")
end