Using breakpoint in Your Web Application

Problem

Your Rails application has a bug that you can find using log messages. You need a heavy-duty debugging tool that lets you inspect the full state of your application at any given point.

Solution

The breakpoint library lets you stop the flow of code and drop into irb, an interactive Ruby session. Within irb you can inspect the variables local to the current scope, modify those variables, and resume execution of the normal flow of code. If you have ever spent hours trying to track down a bug by placing logging messages everywhere, youll find that breakpoint gives you a much easier and more straightforward way to debug.

But how can you run an interactive console program from a web application? The answer is to have a console program running beforehand, listening for calls from the Rails server.

The first step is to run ./script/breakpointer on the command line. This command starts a server that listens over the network for breakpoint calls from the Rails server. Keep this program running in a terminal window: this is where the irb session will start up:

	$ ./script/breakpointer
	No connection to breakpoint service at druby://localhost:42531
	Tries to connect will be made every 2 seconds…

To trigger an irb session, you can call the breakpoint method anywhere you like from your Rails applicationwithin a model, controller, or helper method. When execution reaches that point, processing of the incoming client request will stop, and an irb session will start in your terminal. When you quit the session, processing of the request will resume.

Discussion

Heres an example. Lets say youve written the following controller, and you e having trouble modifying the name attribute of an Item object.

	class ItemsController < ApplicationController
	 def update
	 @item = Item.find(params[:id])
	 @item.value = [default]
	 @item.name = params[:name]
	 @item.save
	 render :text => Saved
	 end
	end

You can put a breakpoint call in the Item class, like this:

	class Item < ActiveRecord::Base
	 attr_accessor :name, :value

	 def name=(name)
	 super
	 breakpoint
	 end
	end

Accessing the URL http://localhost:3000/items/update/123?name=Foo calls Item-Controller#update, which finds Item number 123 and then calls its name= method. The call to name= triggers the breakpoint. Instead of rendering the text "Saved", the site seems to hang and become unresponsive to requests.

But if you return to the terminal running the breakpointer server, youll see that an interactive Ruby session has started. This session allows you to play with all the local variables and methods at the point where the breakpoint was called:

	Executing break point "Item#name=" at item.rb:4 in 
ame=
	 irb:001:0> local_variables
	 => ["name", "value", "_", "__"]
	 irb:002:0> [name, value]
	 => ["Foo", "[default]"]
	 irb:003:0> [@name, @value]
	 => ["Foo", "[default]"]
	 irb:004:0> self
	 => #
	 irb:005:0> self.value = "Bar"
	 => "Bar"
	 irb:006:0> save
	 => true
	 irb:006:0> exit
	Server exited. Closing connection…

Once you finish, type exit to terminate the interactive Ruby session. The Rails application continues running at the place it left off, rendering "Saved" as expected.

By default, breakpoints are named for the method in which they appear. You can pass a string into breakpoint to get a more descriptive name. This is especially helpful if one method contains several breakpoints:

	breakpoint "Trying to set Item#name, just called super"

Instead of calling breakpoint directly, you can also call assert, a method which takes a code block. If the block evaluates to false, Ruby calls breakpoint; otherwise, things continue as normal. Using assert lets you set breakpoints that are only called when something goes wrong (called "conditional breakpoints" in traditional debuggers):

	1.upto 10 do |i|
	 assert { Person.find(i) }
	 p = Person.find(i)
	 p.update_attribute(:name, Lucas)
	end

If all of the required Person objects are found, the breakpoint is never called, because Person.find always returns true. If one of the Person objects is missing, Ruby calls the breakpoint method and you get an irb session to investigate.

Breakpoint is a powerful tool that can vastly simplify your debugging process. It can be hard to understand the true power of it until you try it yourself, so go through the solution with your own code to toy around with it.

See Also

  • Recipe 17.10, "Using breakpoint to Inspect and Change the State of Your Application," covers breakpoint in more detail.
  • http://wiki.rubyonrails.com/rails/show/HowtoDebugWithBreakpoint


Strings

Numbers

Date and Time

Arrays

Hashes

Files and Directories

Code Blocks and Iteration

Objects and Classes8

Modules and Namespaces

Reflection and Metaprogramming

XML and HTML

Graphics and Other File Formats

Databases and Persistence

Internet Services

Web Development Ruby on Rails

Web Services and Distributed Programming

Testing, Debugging, Optimizing, and Documenting

Packaging and Distributing Software

Automating Tasks with Rake

Multitasking and Multithreading

User Interface

Extending Ruby with Other Languages

System Administration



Ruby Cookbook
Ruby Cookbook (Cookbooks (OReilly))
ISBN: 0596523696
EAN: 2147483647
Year: N/A
Pages: 399

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net