Created
December 2, 2025 09:38
-
-
Save amkisko/09a50b10e4ea82b0ac835307a940fe60 to your computer and use it in GitHub Desktop.
Revisions
-
amkisko created this gist
Dec 2, 2025 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,142 @@ RSpec.configure do |config| config.before do |example| @spec_file_path = example.metadata[:example_group][:file_path] @spec_line_number = example.metadata[:example_group][:line_number] def spec_dirname File.dirname(@spec_file_path) end def spec_basename File.basename(@spec_file_path) end if ENV["DEBUG"] Rails.logger.level = 0 puts "Running #{@spec_file_path}:#{@spec_line_number}" end end end with_sql = ENV["DEBUG_SQL"] with_stack = ENV["DEBUG_STACK"] debug_requested = with_sql || with_stack if debug_requested require "amazing_print" def pp(*, **) = ENV["PRETTY"] ? ap(*, **) : puts(*, **) RSpec.configure do |config| config.around do |example| if with_sql subscriber = ActiveSupport::Notifications.subscribe("sql.active_record") do |event| payload = event.payload[:sql] # next if payload.match?(/^(SELECT|SET|SHOW|BEGIN|COMMIT|ROLLBACK|RELEASE|SAVEPOINT)/) # next if payload.include?("audits") next if payload.include?("pg_attribute") type_casted_binds = if event.payload[:type_casted_binds].is_a?(Array) event.payload[:type_casted_binds] elsif event.payload[:type_casted_binds].is_a?(Proc) event.payload[:type_casted_binds].call else [] end if type_casted_binds.is_a?(Array) type_casted_binds.each_with_index.reverse_each do |bind, index| payload = payload.gsub("$#{index + 1}", "'#{bind}'") end end pp(event: "sql.active_record", sql: payload) end end if with_stack trace = TracePoint.new do |tp| next if !tp.path&.start_with?(Rails.root.to_s) next if tp.path&.include?(Rails.root.join("spec/support").to_s) if tp.event == :call method_name = tp.method_id defined_class = tp.defined_class args = [] kwargs = {} begin # Try to get method object - handle both instance and class methods method_obj = begin if defined_class.singleton_class? defined_class.method(method_name) else tp.self.method(method_name) end rescue # Fallback: try instance method begin defined_class.instance_method(method_name) rescue nil end end if method_obj&.respond_to?(:parameters) params = method_obj.parameters binding = tp.binding params.each do |param_type, param_name| next unless binding.local_variable_defined?(param_name) value = binding.local_variable_get(param_name) case param_type when :req, :opt args << value when :key, :keyreq kwargs[param_name] = value when :keyrest kwargs.merge!(value || {}) when :rest args.concat(value || []) end end end rescue # If we can't extract arguments, just continue without them end # Format method display: use . for class methods, # for instance methods method_display = if defined_class.singleton_class? "#{defined_class}.#{method_name}" else "#{defined_class}##{method_name}" end output = { event: tp.event, method: method_display, path: "#{tp.path}:#{tp.lineno}" } output[:args] = args if args.any? output[:kwargs] = kwargs if kwargs.any? pp(output) elsif tp.event == :raise pp({ event: tp.event, raised_exception: tp.raised_exception, path: "#{tp.path}:#{tp.lineno}", method_id: tp.method_id }) end end trace.enable end example.run trace.disable if with_stack ActiveSupport::Notifications.unsubscribe(subscriber) if with_sql end end end