Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strategy advice for advanced Rails debugging?

I've been coding in Ruby/Rails for almost 9 months now, having spent years before that in Python.

While I'm really enjoying Rails, there's one area where I often find myself frustrated: chasing down stubborn bugs. In other languages I can almost always track down difficulties without too much trouble, but when I hit a wall debugging rails, I tend to really hit a wall. I guess what I'm asking is: what strategies do advanced rails users employ to track down more stubborn errors?

At the moment my approach is usually:

  1. Examine the stack trace (most simple bugs solved here)

  2. Run debugger/pry/console & examine the environment, pace through each step if necessary

  3. Google it

  4. Post on stack overflow/github issues

  5. Procrastinate and/or swear profusely

If any advanced rails-ers would share their strategy for chasing down more stubborn bugs, I'd be really appreciative. In short, what do yo do when trace/debugger don't offer any clues?

like image 921
PlankTon Avatar asked Sep 08 '11 11:09

PlankTon


2 Answers

I personally find that firing up the rails console and stepping through things there manually helps sort out most "hard to track down" bugs. However, lately I started using pry and adding "binding.pry" calls into code that I want to debug. It seems the trick is to figure out where to place the binding.pry call. Invaluable in view code as well as complicated test code that you inherited.

like image 155
Kevin Rood Avatar answered Oct 25 '22 05:10

Kevin Rood


Being with Rails mere 5 years, I do not consider myself an advanced Railser, but nevertheless I'll happily share my knowledge. :-)

The main thing when dealing with any (except some very, very trivial ones) is to write a test for this bug.

A few times it happened that I solved the bug at this stage - for example when the bug was related to the automatic class reloading, which is active in development, and turned off in test mode.

Then I usually just place some logger.debug statements with a lot of inspect and caller(0).join("\n\t") in it. Then I very carefully examine the log file.

Because the 'test.log' can have a few hundreds megabytes, I always remember to zero it before I run my test. Also I usually run just one test method at the time, because the output would be unreadable otherwise.

I do not use a dedicated debugger. In some old version of ruby the debugger stopped working, I learned to live without it, and never looked back.


A few utilities which may be useful:

A function defined in my ~/.bashrc, which lets me to invoke a single test method (or a group of methods):

$ testuj test/unit/user_test.rb -n test_name_validations
$ testuj test/unit/user_test.rb -n /_name_/
function testuj () {
  if [ -n "${BUNDLE_GEMFILE}" ]
  then
    # This is a Rails3 project - it is run by `bundle exec`
    ruby -I"lib:test" "$@"
  else
    # This is a Rails1 project. No bundler.
    ruby -e 'ARGV.each { |f| load f unless f =~ /^-/ ; break if f == "-n" }' "$@"
  fi
}

And this method helps me with logging and checking the timing of some steps:

Object.module_eval do
  def czekpoint(note = nil)
    n = Time.now
    $czekpoint_previous ||= n
    $czekpoint_number ||= 0
    $czekpoint_number += 1
    t = n - $czekpoint_previous
    msg = "CZEKPOINT: %2d  %8.6f  %s %s" % [$czekpoint_number, t, caller.first.to_s.in_yellow, note.to_s.in_red]
    Rails.logger.debug msg # In older Rails it was RAILS_DEFAULT_LOGGER
    STDERR.puts msg
    $czekpoint_previous = n
  end
end
like image 38
Arsen7 Avatar answered Oct 25 '22 05:10

Arsen7