DEV Community

Lazy coder
Lazy coder

Posted on

irbrc to help with your efficiency


IRB.conf[:PROMPT][:DEV] = { # name of prompt mode
  :AUTO_INDENT => false,          # disables auto-indent mode
  :PROMPT_I =>  ">> ",            # simple prompt
  :PROMPT_S => nil,               # prompt for continuated strings
  :PROMPT_C => nil,               # prompt for continuated statement
  :RETURN => "    ==>%s\n"        # format to return value
}

#IRB.conf[:PROMPT_MODE] = :MY_PROMPT

# Tracking and Debugging Helpers

# Log method calls with their arguments
# Usage: track_method_calls(User, :save)
def track_method_calls(klass, method_name)
  klass.class_eval do
    old_method = instance_method(method_name)
    define_method(method_name) do |*args, &block|
      puts "Calling #{klass}##{method_name} with args: #{args.inspect}"
      old_method.bind(self).call(*args, &block)
    end
  end
end

# Track SQL queries
# Usage: track_sql_queries
def track_sql_queries
  ActiveSupport::Notifications.subscribe('sql.active_record') do |*args|
    event = ActiveSupport::Notifications::Event.new(*args)
    puts "SQL Query: #{event.payload[:sql]}"
    puts "Duration: #{event.duration.round(2)} ms"
    puts "---"
  end
end

# Count method calls
# Usage: count_method_calls(User, :update)
def count_method_calls(klass, method_name)
  count = 0
  klass.class_eval do
    old_method = instance_method(method_name)
    define_method(method_name) do |*args, &block|
      count += 1
      puts "#{klass}##{method_name} called #{count} times"
      old_method.bind(self).call(*args, &block)
    end
  end
end

# Track object allocations
# Usage: track_allocations { your_code_here }
def track_allocations
  require 'objspace'
  GC.disable
  before = ObjectSpace.count_objects
  yield
  after = ObjectSpace.count_objects
  puts "Object allocations:"
  after.each do |key, value|
    diff = value - before[key]
    puts "  #{key}: #{diff}" if diff != 0
  end
ensure
  GC.enable
end

# Profile code execution
# Usage: profile_code { your_code_here }
def profile_code
  require 'ruby-prof'
  RubyProf.start
  yield
  result = RubyProf.stop
  printer = RubyProf::FlatPrinter.new(result)
  printer.print(STDOUT)
end

# Track method execution time
# Usage: track_time(User, :expensive_method)
def track_time(klass, method_name)
  klass.class_eval do
    old_method = instance_method(method_name)
    define_method(method_name) do |*args, &block|
      start_time = Time.now
      result = old_method.bind(self).call(*args, &block)
      end_time = Time.now
      puts "#{klass}##{method_name} took #{(end_time - start_time) * 1000.0} ms"
      result
    end
  end
end

# Log instance variable changes
# Usage: track_ivar_changes(user, :name)
def track_ivar_changes(object, ivar_name)
  object.define_singleton_method("#{ivar_name}=") do |value|
    old_value = instance_variable_get("@#{ivar_name}")
    instance_variable_set("@#{ivar_name}", value)
    puts "#{object.class}##{ivar_name} changed from #{old_value.inspect} to #{value.inspect}"
  end
end


# Memory usage tracker
# Usage: track_memory { your_code_here }
def track_memory
  memory_before = `ps -o rss= -p #{Process.pid}`.to_i
  yield
  memory_after = `ps -o rss= -p #{Process.pid}`.to_i
  puts "Memory usage increased by #{memory_after - memory_before} KB"
end


def compare_methods(count = 1, *methods)
  require 'benchmark'
  Benchmark.bmbm do |b|
    methods.each do |method|
      b.report(method) { count.times { send(method) } }
    end
  end
  nil
end

def pp_hash(hash, indent=1)
  hash.each do |k, v|
    print "  " * indent
    if v.is_a?(Hash)
      puts "#{k}:"
      pp_hash(v, indent+1)
    else
      puts "#{k}: #{v}"
    end
  end
end

def measure_allocation
  before = GC.stat(:total_allocated_objects)
  yield
  after = GC.stat(:total_allocated_objects)
  puts "Allocated objects: #{after - before}"
end

def http_get(url)
  require 'httparty'
  response = HTTParty.get(url)
  puts "Status: #{response.code}"
  puts "Body: #{response.body}"
end

def explore_relation(relation)
  puts "SQL: #{relation.to_sql}"
  puts "Explained:"
  puts relation.explain
end

def parse_json(json_string)
  require 'json'
  JSON.pretty_generate(JSON.parse(json_string))
end

def list_constants(mod)
  mod.constants.sort.each do |const|
    puts "#{const} = #{mod.const_get(const)}"
  end
end

# Usage: class_hierarchy(Array)
def class_hierarchy(klass)
  hierarchy = [klass]
  while (klass = klass.superclass)
    hierarchy << klass
  end
  hierarchy.each_with_index do |k, i|
    puts "#{' ' * i}#{k}"
  end
end

# Usage: method_info("hello", :upcase)
def method_info(obj, method_name)
  method = obj.method(method_name)
  puts "Name: #{method.name}"
  puts "Owner: #{method.owner}"
  puts "Parameters: #{method.parameters}"
  puts "Arity: #{method.arity}"
  puts "Source Location: #{method.source_location&.join(':')}"
end

# Usage: set_breakpoint(User, :save)
def set_breakpoint(klass, method_name)
  require 'pry'
  klass.send(:define_method, method_name) do |*args, &block|
    binding.pry
    super(*args, &block)
  end
end

# Usage: list_instance_variables(some_object)
def list_instance_variables(obj)
  obj.instance_variables.each do |var|
    puts "#{var}: #{obj.instance_variable_get(var).inspect}"
  end
end

# Usage: show_ancestors(Array)
def show_ancestors(klass)
  puts "Ancestors:"
  klass.ancestors.each { |ancestor| puts "  #{ancestor}" }
  puts "\nIncluded Modules:"
  (klass.ancestors - klass.superclass.ancestors - [klass]).each { |mod| puts "  #{mod}" }
end

# Usage: list_constants
def list_constants
  Module.constants.sort.each do |constant|
    puts constant
  end
end

# Usage: explore_methods("hello")
def explore_methods(obj)
  methods = {
    instance: obj.methods - Object.methods,
    inherited: obj.methods & Object.methods,
    singleton: obj.singleton_methods
  }

  methods.each do |category, method_list|
    puts "#{category.to_s.capitalize} methods:"
    method_list.sort.each { |method| puts "  #{method}" }
    puts
  end
end

# Usage: show_method_source(Array, :map)
def show_method_source(obj, method_name)
  require 'pry'
  obj.method(method_name).source.display
end

# Usage: list_classes
def list_classes
  Object.constants
    .select { |c| Object.const_get(c).is_a? Class }
    .sort
    .each { |klass| puts klass }
end

# Usage: method_location(Array, :map)
def method_location(obj, method_name)
  file, line = obj.method(method_name).source_location
  puts "Defined in #{file}:#{line}"
end

# Usage: subclasses_of(ActiveRecord::Base)
def subclasses_of(klass)
  ObjectSpace.each_object(Class).select { |k| k < klass }
end

def track_changes(target, method_name)
  original_value = target.send(method_name.to_s.sub('=', ''))
  puts "Starting to track changes to #{target}.#{method_name}"
  puts "Initial value: #{original_value.class}"

  trace = TracePoint.new(:line) do |tp|
    #next unless tp.method_id.to_s == method_name.to_s && tp.self.instance_of?(target.class) && tp.self == target
    next unless tp.self.instance_of?(target.class) && tp.self == target && tp.method_id.to_s.include?(method_name.to_s.sub('=', ''))

    current_value = target.send(method_name.to_s.sub('=', ''))
    if current_value != original_value
      puts "\nChange detected in #{target}.#{method_name}:"
      puts "  From: #{original_value.class}"
      puts "  To:   #{current_value.class}"
      puts "  At:   #{tp.path}:#{tp.lineno}"
      puts "  Backtrace:"
      puts caller[0..5].map { |line| "    #{line}" }
      puts '-'*60
      original_value = current_value
    end
  end

  trace.enable
  puts "Tracking enabled. Run 'trace.disable' to stop tracking."

  trace  # Return the trace object so it can be disabled later
end

def track_method(klass, method_name, process=nil)
  trace = TracePoint.new(:call) do |tp|
    next unless tp.method_id.to_s == method_name.to_s

    next unless (klass.is_a?(Class) ? tp.self.is_a?(klass) : tp.self == klass)

    puts '-'*20
    puts "#{tp.path}:#{tp.lineno}"
    puts "#{tp.defined_class}##{tp.method_id}" if tp.defined_class
    process.call if process
  end

  trace.enable
  if block_given?
    yield
    trace.disable
  else
    puts "Tracking enabled. Run 'trace.disable' to stop tracking."
  end

  trace  # Return the trace object so it can be disabled later
end

Enter fullscreen mode Exit fullscreen mode

Top comments (0)