The frame command in Ruby debugger can be pretty useful when you want to dive deep into how some result is being evaluated.


To use it, create a breakpoint in your Ruby code using debugger or byebug. Then enter backtrace to see the stack of methods that were invoked to beget your current execution point:


(byebug) backtrace
--> #0 block in block in <class:CodeLine> at /Users/bill/src/gitclear/app/models/code_line.rb:74
ͱ-- #1 BasicObject.instance_exec(*args) at /Users/bill/.rvm/gems/ruby-3.0.3@gitclear/gems/activesupport-6.1.7.2/lib/active_support/callbacks.rb:427
#2 block in ActiveSupport::Callbacks::CallTemplate.block in make_lambda at /Users/bill/.rvm/gems/ruby-3.0.3@gitclear/gems/activesupport-6.1.7.2/lib/active_support/callbacks.rb:427
#3 block (2 levels) in #<Class:ActiveSupport::Callbacks::Filters::Before>.block (2 levels) in halting(callback_sequence#ActiveSupport::Callbacks::CallbackSequence, user_callback#Proc, halted_lambda#Proc, filter#Proc, name#Symbol) at /Users/bill/.rvm/gems/ruby-3.0.3@gitclear/gems/activesupport-6.1.7.2/lib/active_support/callbacks.rb:198
#4 block (2 levels) in ActiveSupport::Callbacks::CallbackChain.block (2 levels) in default_terminator at /Users/bill/.rvm/gems/ruby-3.0.3@gitclear/gems/activesupport-6.1.7.2/lib/active_support/callbacks.rb:604
ͱ-- #5 Kernel.catch(*args) at /Users/bill/.rvm/gems/ruby-3.0.3@gitclear/gems/activesupport-6.1.7.2/lib/active_support/callbacks.rb:603
#6 block in ActiveSupport::Callbacks::CallbackChain.block in default_terminator at /Users/bill/.rvm/gems/ruby-3.0.3@gitclear/gems/activesupport-6.1.7.2/lib/active_support/callbacks.rb:603
#7 block in #<Class:ActiveSupport::Callbacks::Filters::Before>.block in halting(callback_sequence#ActiveSupport::Callbacks::CallbackSequence, user_callback#Proc, halted_lambda#Proc, filter#Proc, name#Symbol) at /Users/bill/.rvm/gems/ruby-3.0.3@gitclear/gems/activesupport-6.1.7.2/lib/active_support/callbacks.rb:199
#8 block in ActiveSupport::Callbacks::CallbackSequence.block in invoke_before(arg#ActiveSupport::Callbacks::Filters::Environment) at /Users/bill/.rvm/gems/ruby-3.0.3@gitclear/gems/activesupport-6.1.7.2/lib/active_support/callbacks.rb:512
ͱ-- #9 Array.each at /Users/bill/.rvm/gems/ruby-3.0.3@gitclear/gems/activesupport-6.1.7.2/lib/active_support/callbacks.rb:512
#10 ActiveSupport::Callbacks::CallbackSequence.invoke_before(arg#ActiveSupport::Callbacks::Filters::Environment) at /Users/bill/.rvm/gems/ruby-3.0.3@gitclear/gems/activesupport-6.1.7.2/lib/active_support/callbacks.rb:512
#11 block in ActiveSupport::Callbacks.block in run_callbacks(kind#Symbol) at /Users/bill/.rvm/gems/ruby-3.0.3@gitclear/gems/activesupport-6.1.7.2/lib/active_support/callbacks.rb:115
#12 ActiveSupport::Callbacks.run_callbacks(kind#Symbol) at /Users/bill/.rvm/gems/ruby-3.0.3@gitclear/gems/activesupport-6.1.7.2/lib/active_support/callbacks.rb:137
#13 ActiveRecord::Base._run_save_callbacks(&block#Proc) at /Users/bill/.rvm/gems/ruby-3.0.3@gitclear/gems/activesupport-6.1.7.2/lib/active_support/callbacks.rb:824
#14 ActiveRecord::Callbacks.create_or_update() at /Users/bill/.rvm/gems/ruby-3.0.3@gitclear/gems/activerecord-6.1.7.2/lib/active_record/callbacks.rb:457
#15 ActiveRecord::Timestamp.create_or_update(touch#TrueClass, ) at /Users/bill/.rvm/gems/ruby-3.0.3@gitclear/gems/activerecord-6.1.7.2/lib/active_record/timestamp.rb:126
#16 ActiveRecord::Persistence.save!(options#Hash, &block#NilClass) at /Users/bill/.rvm/gems/ruby-3.0.3@gitclear/gems/activerecord-6.1.7.2/lib/active_record/persistence.rb:507
#17 ActiveRecord::Validations.save!(options#Hash) at /Users/bill/.rvm/gems/ruby-3.0.3@gitclear/gems/activerecord-6.1.7.2/lib/active_record/validations.rb:53
#18 block in ActiveRecord::Transactions.block in save!() at /Users/bill/.rvm/gems/ruby-3.0.3@gitclear/gems/activerecord-6.1.7.2/lib/active_record/transactions.rb:302
#19 block in ActiveRecord::Transactions.block in with_transaction_returning_status at /Users/bill/.rvm/gems/ruby-3.0.3@gitclear/gems/activerecord-6.1.7.2/lib/active_record/transactions.rb:354
#20 block in ActiveRecord::ConnectionAdapters::DatabaseStatements.block in transaction(requires_new#NilClass, isolation#NilClass, joinable#TrueClass) at /Users/bill/.rvm/gems/ruby-3.0.3@gitclear/gems/activerecord-6.1.7.2/lib/active_record/connection_adapters/abstract/database_statements.rb:320
#21 block in ActiveRecord::ConnectionAdapters::TransactionManager.block in within_new_transaction(isolation#NilClass, joinable#TrueClass) at /Users/bill/.rvm/gems/ruby-3.0.3@gitclear/gems/activerecord-6.1.7.2/lib/active_record/connection_adapters/abstract/transaction.rb:319
#22 block (2 levels) in ActiveSupport::Concurrency::LoadInterlockAwareMonitor.block (2 levels) in synchronize at /Users/bill/.rvm/gems/ruby-3.0.3@gitclear/gems/activesupport-6.1.7.2/lib/active_support/concurrency/load_interlock_aware_monitor.rb:26
ͱ-- #23 #<Class:Thread>.handle_interrupt() at /Users/bill/.rvm/gems/ruby-3.0.3@gitclear/gems/activesupport-6.1.7.2/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25
#24 block in ActiveSupport::Concurrency::LoadInterlockAwareMonitor.block in synchronize at /Users/bill/.rvm/gems/ruby-3.0.3@gitclear/gems/activesupport-6.1.7.2/lib/active_support/concurrency/load_interlock_aware_monitor.rb:25
ͱ-- #25 #<Class:Thread>.handle_interrupt() at /Users/bill/.rvm/gems/ruby-3.0.3@gitclear/gems/activesupport-6.1.7.2/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21
#26 ActiveSupport::Concurrency::LoadInterlockAwareMonitor.synchronize at /Users/bill/.rvm/gems/ruby-3.0.3@gitclear/gems/activesupport-6.1.7.2/lib/active_support/concurrency/load_interlock_aware_monitor.rb:21
#27 ActiveRecord::ConnectionAdapters::TransactionManager.within_new_transaction(isolation#NilClass, joinable#TrueClass) at /Users/bill/.rvm/gems/ruby-3.0.3@gitclear/gems/activerecord-6.1.7.2/lib/active_record/connection_adapters/abstract/transaction.rb:317
#28 ActiveRecord::ConnectionAdapters::DatabaseStatements.transaction(requires_new#NilClass, isolation#NilClass, joinable#TrueClass) at /Users/bill/.rvm/gems/ruby-3.0.3@gitclear/gems/activerecord-6.1.7.2/lib/active_record/connection_adapters/abstract/database_statements.rb:320
#29 ActiveRecord::Transactions.with_transaction_returning_status at /Users/bill/.rvm/gems/ruby-3.0.3@gitclear/gems/activerecord-6.1.7.2/lib/active_record/transactions.rb:350
#30 ActiveRecord::Transactions.save!() at /Users/bill/.rvm/gems/ruby-3.0.3@gitclear/gems/activerecord-6.1.7.2/lib/active_record/transactions.rb:302
#31 ActiveRecord::Suppressor.save!() at /Users/bill/.rvm/gems/ruby-3.0.3@gitclear/gems/activerecord-6.1.7.2/lib/active_record/suppressor.rb:48
#32 block (2 levels) in CommitConcerns::CommitImpactConcerns.block (2 levels) in update_scores_individually(iteration_lines#Array, is_duplicate#NilClass, updated_commit_ids#Set, preloaded_lines#Array, logger#ActiveSupport::Logger) at /Users/bill/src/gitclear/app/lib/commit_concerns/commit_impact_concerns.rb:184
ͱ-- #33 Array.each at /Users/bill/src/gitclear/app/lib/commit_concerns/commit_impact_concerns.rb:181
#34 block in CommitConcerns::CommitImpactConcerns.block in update_scores_individually(iteration_lines#Array, is_duplicate#NilClass, updated_commit_ids#Set, preloaded_lines#Array, logger#ActiveSupport::Logger) at /Users/bill/src/gitclear/app/lib/commit_concerns/commit_impact_concerns.rb:181


Each method in that stack is a location that can be visited by invoking frame [stack index].


So, for example, if I enter frame 34 from the execution point shown in that stacktrace, my debugging context switches to the update_scores_individually method. There, I can poke at the variables that exist in that method but wouldn't be available to the method that my breakpoint originated at.


If you want to return to your original breakpoint after moving to a different frame, you can enter frame 0.


Google says that other versions of Ruby debugger have a command named jump. I presume it functions similarly?