Ruby / Debugging
From WhyNotWiki
Ruby / Debugging edit (Category edit)
Contents |
[edit] General
Debugging Ruby can be made difficult when the classes/modules you are working with may have been reopened any number of times anywhere in your code base. By the time other modules have been mixed in and methods overrided, the resulting class may be completely different than how you think it is. How do you even know what methods exist??
These might help a little:
- Object#public_methods
- Object#private_methods
- Object#protected_methods
- instance_variables
- instance_methods
How to examine call stack?
Kernel#caller
[edit] Debugging: Why can't it load [filename]??
Say, for instance, it's not finding a file named 'foo' when you do require 'foo'.
- The first thing to check, of course, is the spelling of the filename.
- Next, check
$LOAD_PATH... The file (relative path) must exist in one of the paths listed there, or it won't find it. - Unless you're using RubyGems or some other library that changes the default behavior of
require/load...
Here's some debug code I used one time. Not sure it's generally useful though...
p $LOAD_PATH
$LOAD_PATH.each {|d| print "For #{d}:"; p (Dir.entries(d).grep(/foo/) rescue []) }
puts "Was found in: " + $LOAD_PATH.find {|d| (Dir.entries(d) rescue []).include?('foo.rb') }
require 'foo'
[edit] Problem: inspect is too verbose?
Here's one way to just have it print the methods you care about:
[:whatever, :some_method].each {|method| puts "#{method} = #{self.send(method)}"}
as an alternative to:
puts self.inspect
Also consider using pp object or puts object.to_yaml, as they can be far more readable a lot of th etime.
[edit] Problem: you can't always print to stdout to do debugging
Sometimes I look at someone else's code (like Rails) to try to figure out how it works. Sometimes just looking at the code doesn't tell me enough; I need to inspect the values of variables as they are running.
So.... I can either try to mess with the breakpointer/debugger... or I could just dump the values I want to a file and inspect it after I run the code.
You never know what logging facilities are available. Best to just rely on primitive built-in file-writing mechanism, like those that the File class provides.
Make sure your ~/temp directory is writable, and then add this wherever you want to dump stuff.
File.open("/home/tyler/temp/debugging.log", "a") { |file| file.puts an_interesting_variable }
or
File.open("debugging.log", "w") { |file| file.puts '' }
def out(out); File.open("debugging.log", "a") { |file| file.puts out }; end
watch cat $debugging.log
[edit] Why doesn't it show the entire backtrace?
[Questions (category)][Problems (category)]
Sometimes, when the backtrace is really long, Ruby tries to be helpful and omits part of the backtrace (replacing the omitted section with the number of lines that were omitted, as in "... 54 levels...", sort of like this:
./script/../config/../../lib/rails_profiler.rb:39:in `log': You have a nil object when you didn't expect it! (NoMethodError)
The error occurred while evaluating nil.info from ./script/../config/../vendor/rails/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb:145:in `execute'
from ./script/../config/../vendor/rails/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb:346:in `catch_schema_changes'
from ./script/../config/../vendor/rails/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb:145:in `execute'
from ./script/../config/../vendor/rails/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb:160:in `insert'
from ./script/../config/../vendor/rails/activerecord/lib/active_record/base.rb:1811:in `create_without_callbacks'
from ./script/../config/../vendor/rails/activerecord/lib/active_record/callbacks.rb:254:in `create_without_timestamps'
from ./script/../config/../vendor/rails/activerecord/lib/active_record/timestamp.rb:39:in `create'
from ./script/../config/../vendor/rails/activerecord/lib/active_record/base.rb:1789:in `create_or_update_without_callbacks'
... 54 levels...
from ./script/../config/../vendor/rails/activesupport/lib/active_support/dependencies.rb:495:in `require'
from ./script/../config/../vendor/rails/railties/lib/commands/server.rb:40
from ./script/server:4:in `require'
from ./script/server:4
I have to say, however, that despite the good intentions of whomever added this "feature", it is often not helpful. What if I want to see the entire backtrace?
Unfortunately, I don't think there's any (easy, built-in) way to enable the showing of the full backtrace.
Instead one is forced to rescue the exception yourself and print out the full backtrace.
You have to go to (one of the) outer file (the one listed at the bottom of the incomplete backtrace), and surround the offending line/lines with something like this:
begin # block within which the exception is raised rescue Exception => exception puts exception.class.name + ": " + exception.message puts exception.backtrace.join( "\n" ) end
So it's doable, but a bit of a pain...
And you have to remember to remove that code when you are done...
References:
- http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/98649 Re: Can't see entire traceback
[edit] Libraries
[edit] Unroller
| Homepage: | http://unroller.rubyforge.org/
|
|---|---|
| Project/Development: | http://rubyforge.org/projects/unroller
|
| Description: | A tool for generating human-readable "execution traces". Displays the source code on your screen in real-time as it is executed. Want to know what goes on behind the scenes when you call some 3rd-party method? Trace the method call and find out!
|
| Authors: | Tyler Rick
|
[edit] RuntimeProfile
| Project/Development: | http://rubyforge.org/projects/runtimeprofile/
|
|---|---|
| Description: | Diagnostic utility to track, during the runtime, which file and line classes, modules, and methods are added and changed.
|
| Readiness: | This Project Has Not Released Any Files, 2007-05-11 20:21
|
