Skip to content

Instantly share code, notes, and snippets.

@willnet
Last active August 7, 2023 02:06
Show Gist options
  • Select an option

  • Save willnet/31a255f66312a41b054ed9b5101cf4e9 to your computer and use it in GitHub Desktop.

Select an option

Save willnet/31a255f66312a41b054ed9b5101cf4e9 to your computer and use it in GitHub Desktop.
get association models
require 'set'
class InspectAssociations
def self.call(model)
new.call(model)
end
def call(model)
return if set.include?(model)
set.add(model)
model.class.reflections.keys.each do |name|
reflection = model.class.reflections[name]
assoc = model.association(name.to_sym)
if reflection.collection?
children = assoc.reader
children.each { |child| call(child) }
else
child = assoc.reader
call(child) if child
end
end
pp set
end
private
attr_reader :model
def set
@set ||= Set.new
end
end
class InspectSaveChain
def self.call
new.call
end
def initialize
@indent = 0
end
attr_accessor :indent, :last_call_method, :last_call_class, :last_return_method, :last_return_class
def autosave_method?(tp)
tp.method_id.match?(/autosave_associated_records_for_/)
end
def save_method?(tp)
tp.method_id == :save || tp.method_id == :save!
end
def duplicate_save_method_call?(tp)
last_call_method == tp.method_id && last_call_class == tp.self.class
end
def duplicate_save_method_return?(tp)
last_return_method == tp.method_id && last_return_class == tp.self.class
end
def autosave_to_save?(tp)
(tp.method_id == :save || tp.method_id == :save!) && last_call_method&.match?(/autosave_associated_records_for_/)
end
def update_last_call(tp)
self.last_call_class = tp.self.class
self.last_call_method = tp.method_id
end
def update_last_return(tp)
self.last_return_class = tp.self.class
self.last_return_method = tp.method_id
end
def indent_stack
@indent_stack ||= []
end
def call
trace = TracePoint.new(:call, :return) do |tp|
if tp.event == :call
if autosave_method?(tp)
update_last_call(tp)
puts "#{' ' * (indent * 2)}#{tp.self.class.name}##{tp.method_id}"
elsif save_method?(tp) && !duplicate_save_method_call?(tp)
if autosave_to_save?(tp)
self.indent += 1
indent_stack.push(2)
else
indent_stack.push(1)
end
update_last_call(tp)
puts "#{' ' * (indent * 2)}#{tp.self.class.name}##{tp.method_id}"
self.indent += 1
end
else # :return
if save_method?(tp) && !duplicate_save_method_return?(tp)
self.indent -= indent_stack.pop unless indent_stack.empty?
update_last_return(tp)
end
end
end
trace.enable
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment