CodeBuddy: See your Ruby stack come alive!
Alex Rothenberg, Daniel Higginbotham and I just published a new gem called CodeBuddy that displays a Ruby stack trace inside your browser like this:
The idea is that you can see both the stack trace and code snippets from the corresponding files at the same time, to make it easier to understand what was going on. You can move up and down the stack just by pressing the up/down arrow keys, or by clicking on a line in the stack trace:
As you move, the code snippet in the center of the screen will update, showing you the path the Ruby interpreter took through your application’s code.
Use it in your Rails app
If you’re working on a Rails application, then just add the “code_buddy” gem to your Gemfile like this - to avoid security issues CodeBuddy will only function in the development environment:
group :development do gem "code_buddy" end
And then install it using Bundler:
$ bundle install
Now whenever an exception occurs in your Rails app, the Rails exception page will appear as usual, but each file in the stack trace will now appear as a link:
When you click any of these links CodeBuddy will appear, displaying code from the selected file.
If you’re using Rails 2.3.x, you can use CodeBuddy by adding these two lines to your config/environments/development.rb file:
config.gem 'code_buddy' config.middleware.use "CodeBuddy::ShowApp"
Run it as a Sinatra app
If you’re working on a Ruby project that is not a Rails application, or if you want to look at a stack trace generated by “puts caller” or in some other way you can run CodeBuddy as a standalone Sinatra app, like this:
$ gem install code_buddy $ code_buddy == Sinatra/1.1.0 has taken the stage on 4567 for development with backup from...
Now if you open http://localhost:4567 you’ll get a form like this:
Here you can copy/paste a Ruby stack from your console or elsewhere and click “submit” to see it inside CodeBuddy. As long as the file paths in the stack can be found on your machine they will appear properly in CodeBuddy. You can even paste a stack containing relative paths, as long as you run the code_buddy command from the directory the paths are relative to.
This form is also available when CodeBuddy is running inside your Rails app if you click the “Paste Stack” link near the top right corner. By the way, the reason we disabled CodeBuddy outside of the development environment is that this form would be a huge, gaping security hole if CodeBuddy were active in the production or other server environment. This is because you can type any file path and line number you’d like into the form, and CodeBuddy will display the contents of the specified files. This is definitely not something you want to make available to anonymous users on the Internet in production! In the future we may provide options for running CodeBuddy in non-development environments, such as on an integration or staging server, if you’re sure it won’t present a security risk.
Detailed example
Let’s create a new Rails 3 app together, and try out CodeBuddy. I’ll create a new application from scratch called “code_buddy_example:”
$ rails new code_buddy_example create create README create Rakefile create config.ru create .gitignore create Gemfile create app create app/controllers/application_controller.rb create app/helpers/application_helper.rb... etc ...
$ cd code_buddy_example/
And let’s go ahead and add CodeBuddy to the development environment right away in the Gemfile:
source 'http://rubygems.org'gem 'rails', '3.0.3' group :development do gem 'code_buddy' end
etc...
And now I’ll install it using bundler:
$ bundle install Fetching source index for http://rubygems.org/ Using rake (0.8.7) Using abstract (1.0.0) Using activesupport (3.0.3) Using builder (2.1.2)... etc ...
Using coderay (0.9.6) Using json_pure (1.4.6) Using tilt (1.1) Using sinatra (1.1.0) Installing code_buddy (0.0.6) Using thor (0.14.6) Using railties (3.0.3)
... etc ...
Your bundle is complete! Use
bundle show [gemname]
to see where a bundled gem...Your bundle was installed to
/Users/pat/.rvm/gems/ruby-1.8.7-p302
You can see the CodeBuddy gem was installed, along with a few others CodeBuddy depends on like Sinatra and Coderay. We use Coderay to provide the Ruby syntax color highlighting.
Now before I go any farther, let’s take a look at the Rack middleware stack:
$ rake middleware (in /Users/pat/rails-apps/code_buddy_example) use ActionDispatch::Static use Rack::Lock use ActiveSupport::Cache::Strategy::LocalCache use Rack::Runtime use Rails::Rack::Logger use CodeBuddy::ShowApp use CodeBuddy::ShowExceptions use ActionDispatch::RemoteIp use Rack::Sendfile use ActionDispatch::Callbacks use ActiveRecord::ConnectionAdapters::ConnectionManagement use ActiveRecord::QueryCache use ActionDispatch::Cookies use ActionDispatch::Session::CookieStore use ActionDispatch::Flash use ActionDispatch::ParamsParser use Rack::MethodOverride use ActionDispatch::Head use ActionDispatch::BestStandardsSupport run CodeBuddyExample::Application.routes
You’ll notice CodeBuddy appears twice. First a Rack middleware component called “CodeBuddy::ShowApp” was added by the gem. This displays the CodeBuddy page whenever the user accesses a URL matching “/code_buddy”. Behind the scenes, CodeBuddy::ShowApp actually runs the Sinatra app I mentioned above, right inside your Rails application. Kind of cool!
Second, you can see another Rack middleware component called “CodeBuddy::ShowExceptions.” CodeBuddy replaces the standard Rails ActionDispatch::ShowExceptions middleware component with a modified version, using “middleware.swap.” ActionDispatch::ShowExceptions is what displays the Rails exception pages, and the CodeBuddy version is identical, except that each line in the stack trace is displayed as a link to a “/code_buddy/... ” URL.
Now let’s finish our silly sample app by generating a controller to display a default home page:
$ rails g controller welcome create app/controllers/welcome_controller.rb invoke erb create app/views/welcome invoke test_unit create test/functional/welcome_controller_test.rb invoke helper create app/helpers/welcome_helper.rb invoke test_unit create test/unit/helpers/welcome_helper_test.rb etc...
I’ll edit app/controllers/welcome_controller.rb and add some code to immediately throw an exception:
class WelcomeController < ApplicationController def index raise 'exception' end end
Now I’ll set this as my home page in config/routes.rb:
root :to => "welcome#index"
And finally I’ll delete my static home page:
$ rm public/index.html
Now if I run my server and access http://localhost:3000 I’ll immediately run into the exception... and clicking any of the links in the stack trace will take me to CodeBuddy!
It’s actually quite interesting to follow the stack down from the welcome controller’s action all the way through the rack middleware stack... all the way to the script/server command. Using Webrick from my laptop’s command line I get 82 different levels in my stack trace! Amazing - who knew so much code was executed before the Ruby interpreter ever reached my application!
Feedback welcome
Alex, Daniel and I would love to hear if the gem works for you, and if you have any suggestions - what else could we show in CodeBuddy? How else could it be used? What features is it missing?