Interactive Rails Console

One of the features that several of the webapps I’ve worked on have had, is interactive consoles that allow you to enter some form of code, and see that run inside the webapp process itself. At Ning, we used jruby on rails for one of the admin apps, and it was a life saver to be able to execute debugging code on the app, and see exactly how the app itself was interpreting the code. At Apple, we have an interactive Groovy console that serves the same purpose.

So, when I was working on my latest app, I wanted to add the same piece of functionality. Here’s how I did it. It’s straight forward, and not too complicated, but it has a nice feature that I’ve added after my experience with the previous consoles I’ve used. One of the big drawbacks with the other consoles, was that you would end up hitting back and submit over and over as you refined your code. I wanted to minimize that in the spirit of . Here’s how I did it.

Add a new controller to your rails app (in this case, I named it console)

class ConsoleController < ApplicationController
  
  helper :application        
  include ApplicationHelper  
    
  def index
    
  end
  
  
  def execute
    begin               
      @script = params[:script]  
      rendering_start = Time.now    
      @output = eval(@script)   
      @rendering_time = ((Time.now - rendering_start)* 1000.0).to_i
    rescue Exception => ex
        @output =  ex.inspect  + "\n" + ex.backtrace.join("\n") 
    end    
  end
end

Then you’ll need to create the following views
views/console/_console_form.html.erb


<%= form_tag(console_path, :method => "post") do %>
  <%= label_tag(:script, "Script:") %>
	<br/>
  <%= text_area_tag :script , @script || '', :size => "100x20" %>
	<br/>
  <%= submit_tag("Execute!") %>
<% end %>

views/console/index.html

<% content_for :right_bar do %>
  <p></p>
<% end %>

<%= render 'console_form' %>


views/console/execute.html
<!-- This will make the rails renderer send this output fragment to the  'yield :right_bar' block -->
<% content_for :right_bar do %>
  <p><%= "Execution time: #{@rendering_time} milliseconds" %></p>
<% end %>

<%= render 'console_form' %>

<div id=console_output>
	<pre>Script Output:
		<%= @output %>
	</pre>
</div>

You may be wondering what that content_for call is doing. In my app, I have a top bar, bottom bar (actually two of them, a right bar, and a left bar, and a center area that gets the main content). In this case, the right bar is getting the content from that call. It allows me to have a sort of context sensitive menu for each page (while I have a site wide menu on the left hand bar). I won’t muddy the waters by pasting my main layouts and css here, but you get the idea.

Now, the new page should be usable. After each execution, the edit box is prepopulated with the code you just submitted, so making corrections, or changes is very quick and easy. This will also tell you how long the script you just ran actually took (it’s not a hi-res timer, but it’s close enough for government work).

The really nice thing about this, is you can use your active record classes in here (or MongoMapper if you’re one of the cool kids). So, I can easily just run code like

User.find_by_id(5)[:username]

and see what my app will return for that database record.

It should be noted that this console can be very dangerous. There are no controls around deleting or updating data, so you need to be very careful about how you use this, and also make sure that you don’t expose this in any public site, as it’s sure to be abused at some point). I would add specific security checks for things like a specific user account, or Rails.env.development? ). I would probably also look at disabling this in the routes for the deployed app, just to be on the safe side.

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.