CSC/ECE 517 Fall 2013/ch1 1w12 vn
Debugging in Ruby on Rails
Introduction
Rails is an open-source web application framework which makes use of Ruby programming language. With its huge library of gems and support for MVC architecture, it provides an easy and clean approach for creating pages, talking to web server and dealing with databases. Debugging is always an important part of any application development for which Rails provides a tremendously good support despite being an interpreted language as opposed to C or Java or any other compiled language.
Debugging Options
Rails provides a range of options to make debugging easier. Some of these options have been discussed in the sections below. <ref>http://guides.rubyonrails.org/debugging_rails_applications.html</ref>
Debug Helpers
One of the easiest ways to debug is to simply output the value of different variables which provides us the first look into what could be going wrong. This could be done in all of models, views and controllers. Rails provides three methods-debug, to_yaml and inspect to achieve this task. These methods create human-readable data from any object.<ref> http://ruby-doc.org/core-2.0.0/Object.html </ref> The examples below show the output when these methods are used in a view.
Code | Output |
---|---|
<%= @users.to_yaml %> | --- - !ruby/object:User attributes: id: 2 name: Jimmy Page email: jimmy.page@gmail.com created_at: 2013-09-14 02:37:16.322638000 Z updated_at: 2013-09-16 20:38:04.250678000 Z |
<%= @users.inspect %> | #<ActiveRecord::Relation [#<User id: 2, name: "Jimmy Page", email: "jimmy.page@gmail.com", created_at: "2013-09-14 02:37:16", updated_at: "2013-09-16 20:38:04">]> |
<%= debug @users %> |
--- - !ruby/object:User attributes: id: 2 name: Jimmy Page email: jimmy.page@gmail.com created_at: 2013-09-14 02:37:16.322638000 Z updated_at: 2013-09-16 20:38:04.250678000 Z |
Logger
Logger class in Ruby helps us log information at runtime . Depending on what we choose to save in the log file, it can give us a variety of information such as what SQL queries were sent to databases, methods executed on the controller, attributes of the controller. The default logger for Rails is ActiveSupport::Logger which creates a file(eg. development.log for development environment) under log/ directory. There are six logging levels supported by Logger class [1]. http://www.ruby-doc.org/stdlib-2.0.0/libdoc/logger/rdoc/Logger.html
Error Name | Error Level | Description |
---|---|---|
UNKNOWN | 5 (highest) | An unknown message that should always be logged. |
FATAL | 4 | An error that cannot be handled and results in a program crash |
ERROR | 3 | An error that cannot be handled |
WARN | 2 | A warning |
INFO | 1 | Information about system operation |
DEBUG | 0 (lowest) | Information for developers |
Examples
logger.info "Users information successfully displayed" logger.debug "Users contains #{@users}" logger.fatal "The program could crash"
The different logging levels determine the importance of the message and whether a message is logged or not depends on the current severity level set for an environment. Logger class logs all the messages for which severity level is same or above the current level set. The default logger level for development and production environment is debug and info respectively.
Purpose | Command/Method/Procedure |
---|---|
Change default log level | config.log_level = :info #in any environment initializer
Rails.logger.level = 0 #anywhere |
Configure a new logger | config.logger = Logger.new(...)
User can pass STDOUT/STDERR or name of a file to the initializer depending on where the log messages need to be sent. The Logger class provides options which age the logfile when it reaches a certain size or time (daily/weekly/monthly etc). logger = Logger.new('development.log', 'daily') |
Clear log messages | rake log:clear |
Display log file information on terminal window(UNIX) | tail -f log/development.log |
Put custom messages for debug in models/controllers/views | logger.debug
logger.debug_variables |
Put custom messages for debug in any other custom class | RAILS_DEFAULT_LOGGER |
Change format of logger messages | Override method format_messages(level, time, progname, message) |
Tagged Logging
Debugging a large application could become cumbersome if user decides to log every minor information. Sure removing some of the low level messages could reduce clutter but it is not always an effective solution. luckily ActiveSupport::TaggedLogging class provides a way to filter log messages on the basis of tags which could be anything from subdomains to request ids. User can simply grep into or search log file(s) using tags and look for relevant results quickly.
logger = ActiveSupport::TaggedLogging.new(Logger.new('logfile.log')) #creates a new logger logger.tagged("USR") { logger.info "User info obtained" } #Logs as "[USR] User info obtained" logger.tagged("USR", "Jimmy") { logger.info "Jimmy logged in" } #Logs "[USR] [Jimmy] Jimmy logged in"
logger.tagged("USR") do logger.tagged("Jimmy") { logger.info "Jimmy there" } logger.info "USR there" end # logged as "[USR] [Jimmy] Jimmy there\n[USR] USR there\n"
Debugger Gem
Debugger gem provides a command-line interface for debugging Rails applications step by step as opposed to just logging information which we have discussed so far. With the help of debugger gem, user can put breakpoints, go through code step-wise, inspect contents of variables. The section below provides basic steps to install and use debugger.
- Installation
Run the following command in the command window/terminal.
$ gem install debugger
- Invoke debugger
User can invoke debugger from inside the code by calling debugger method.
- Start Web Server
Start web server in a separate window using --debugger option
$rails server --debugger
- Execute Code
Execute the code as usually and as soon as it comes across debugger method, the code execution will stop and wait for further instructions from the user. The arrow shows where in code has debugger currently stopped.
- Commands
Enter help on the command prompt to find all the available commands user can use at this point.
For further information about a command, use the command
$ help <method>
Ruby-debug Gem
This is another way to debug Ruby application where we need to dig deep into our code for finding the root cause of a problem. We use debugger gem for this process. Tool used earlier for debugging was: “script-breakpointer”. Before staring debugging, your web-server must be started with the option –debugger. Since Rails 2.0, Rails has had built-in support for debugging.
Steps to be followed are mentioned below :
- Install debugger gem :
gem ruby-debug –y #(Here, -y is for dependencies)
- Go to config file and add below command :
require ‘ruby-debug’
- Invoke the debugger, call ‘debugger’ method on file. Put a breakpoint using ‘debugger’ in a file , find the bug and start the server again.
rails server --debugger
- Now, a debugger prompt will be opened which will look like this:
- Use ‘help’ for available commands. We can also get a list of directives with "help", or "help backtrace" for the usage of specific directive. 'list', to take a look at where the application stops. Some useful commands are mentioned below :
Command | Explanation |
---|---|
Backtrace | To check all the previous code. To move inside the trace, use frame_n_command |
Thread | To switch between threads, list the ongoing thread, its status, to stop a thread, resume and to switch its context. |
List | lists all the code |
info breakpoints _n_ or info break _n | list breakpoints |
Some other useful commands are ‘exit’, ‘finish’,‘step’, ‘continue’, ‘next’, ‘print’.
You can use ‘var’ method to print the variables and ‘display’ to watch the variables. To stop displaying, we use ‘undisplay_variableNumber’. You can further debug into the code with ‘irb’ command. We can open as many irb sessions.
Pry Gem
Pry is is a runtime developer console and an alternative to IRB(what?). It provides many features for debugging code easily such as syntax highlighting, code indentation, ability to check source code or documentation without interrupting the current session. There is an indenting problem with IRB, Pry solves this problem by resetting the terminal output as soon as a new line is entered.
Installation Steps
- Install Pry
gem install pry
- Load Pry
require “pry” or –r pry
- Start a Pry session by a method. This method gives access to the data like variables.
binding.pry.
- Run the script. This will display the pry session.
ruby -r pry file.rb.
- We can check the binded data by command
ls #we can just type the name also
- To show the source code/documentation of a method
show-method #or show –doc
- To move out of a breakpoint
CTRL+D
Graphical Debugger
Rubymine, a commercial IDE by JetBrains, has a graphical debugger for ruby and rails code. It provides important and useful features such as smart breakpoints, dedicated view for watches and stack, expression evaluator, etc. Some of the key features related to debugging are presented below.
- Options
Rubymine debugger provides a lot of other options for debugging.
- Breakpoint
One can put breakpoint by simply clicking on the start of the line in the window or pressing Ctrl+Shift+F8. Breakpoint feature highlights the corresponding line in the code.
- Frames, Variables and Watches
Rubymine debugger shows a separate window for frames, variables and watches when the execution hits a breakpoint. User can look in the corresponding window for more information.
- Evaluate code and expressions
Users can type in expression or code and evaluate it when the breakpoint is hit or on the fly.
Analysis
As one can gather from the information provided in the previous sections, there are quite a few debugging options available to tackle bugs in Rails applications. Depending on the severity of bug encountered, one can simply choose to output object contents or debug stepwise. The choice also depends on whether the debugger is free or commercially available. Here is a brief analysis.
Debug Option | Free/Commercial | Comments |
---|---|---|
Debug Helpers | Free | Inspect the contents of an object |
Logger | Free | Support for outputting the contents of an object |
Tagged Logging | Free | Support for outputting the contents of object. Tagging feature quite useful for multi-user/large applications. |
debugger gem | Free | Support for step-wise command-line debugging. Lots of advanced features available. |
debug-ruby gem | Free | ..... |
pry gem | Free | ... |
Rubymine | Commercial | Support for step-wise graphical debugging. Lots of advanced features available. |
Additional Info
The information provided in the sections above are mostly effective for general debugging in Rails. There are more options available which provide other useful features for debugging purposes.
For more specific cases such as memory leak debugging, other choices are also available.
References
<references />