Rails 2.3+ and Rails 3 rely on Rack, a minimal (and awesome) interface between Ruby and webservers. This has many advantages, one of which is the ability to easily swap Rack applications (middlewares) in & out of your Rails app. Modularity FTW!
One fun (and useful) example of a Rack middleware is a Firebug logger written by Simon Jefford for the CodeRack competition. This middleware allows you to send arbitrary messages directly to Firebug. Why? Since you’re already debugging much of your Rails app in a browser anyway, sending debug output to your browser’s console (instead of tailing a log file) makes a lot of sense.
NOTE: FirebugLogger plays nice with WebKit’s Web Inspector as well.
Simon also released a Rails plugin that you can install to set up the middleware for you, but it’s more fun (and informative) to set it up yourself. Here’s how:
The goal is to be able to send arbitrary messages to Firebug from any controller or view.
Rails autoloads (and namespaces) any code placed in the lib directory, so that is where we’ll place our FirebugLogger code. Grab the code from my gist, which is a fork of Simon’s original with minor improvements, and place it inside your Rails app in:
Rails will load the code for us, but we need to manually activate the middleware. Since this bit of code is only useful during development, we’ll load it up in that environment only.
# config/environments/development.rb # ... other stuff ... config.middleware.use ::Rack::FirebugLogger
Using the middleware is pretty straight forward. It will process an array of arrays, each of which has a log level and a message. Add a single line like the one below to an existing controller action and load up the page:
# app/controllers/posts_controller.rb class PostsController < ApplicationController def index @posts = Post.all request.env['firebug.logs'] = [[:info, "hello from rack!"]] end # ... other actions ... end
Open Firebug and you should see “hello from rack!” glaring back at you. You can do the same thing in views:
# app/views/posts/index.html.erb <% request.env['firebug.logs'] = [[:warn, "inside a view!"]] %>
Adding a Helper
Using the logger like this is a bit tedious, and it’s not easy to create multiple messages for a single request. Let’s wrap the functionality up into a method that we can call. This method should be placed in the application controller so that all other controllers inherit it.
# app/controllers/application_controller.rb class ApplicationController < ActionController::Base # ... other stuff ... helper_method :firebug private def firebug(message,type = :debug) request.env['firebug.logs'] ||=  request.env['firebug.logs'] << [type.to_sym, message.to_s] end end
This method will initialize an empty array the first time it is called and then push new messages on to the array on subsequent calls. Notice that it calls to_s on the message variable before passing it on. This means you can send the method a string or any object that responds to to_s and it will just work. Specifying a log type is optional, the method is private and it is explicitly added as a helper_method so that you can access it from views as well.
Now writing logs to Firebug is as easy as:
firebug "woop woop!" # optionally specify a log level firebug "it's a trap!", :warning
Here are a few ideas of helpful messages to send to Firebug:
# inspect the attributes of an object firebug @posts.first.inspect # dump the session firebug session # check a user's roles firebug current_user.roles.inspect
I highly encourage you to try this in one of your Rails apps. It has proven a useful addition to my toolkit. Let me know how it works for you by leaving a comment!