Toward a Swankier Rails Console

As Rails developers, we spend a fair amount of time in the Rails console, which is itself just the native Interactive Ruby Shell (IRB). By default, it’s not particularly pretty…

$ rails c
irb(main):001:0> def hello
irb(main):002:1> puts “hello”
irb(main):003:1> end
=> :hello
irb(main):004:0> hello
hello
=> nil
irb(main):005:0>

…but it gets the job done. We were content with it, because we didn’t know things could be better.

But then we started worrying. Our app lives on Heroku, and there are several other Heroku “forked” apps that give us non-production environments for various levels of testing. And with many shells open at once, it could be possible to accidentally run code against our production database that was intended for casual testing with fake data. (We have code reviews for scripts that modify production data, but what if the script was only ever supposed to be run locally?) The fact that we hadn’t yet made that sort of mistake wasn’t particularly reassuring.

Then we discovered .irbrc files, the Ruby config files for the IRB shell. Our first move was to add a visual indicator of the current Rails environment (click that link for more information on these options):

Which gave us the environment name on every line:

$ heroku run rails c –app my-development-app
Development (main):001:0> def hello
Development (main):002:1> puts “hello”
Development (main):003:1> end
=> :hello
Development (main):004:0>

This was helpful, but we found the production shell wasn’t quite alarming enough. So we gave it a little more oomph:

Which gives us:

$ heroku run rails c –app my-production-app
PRODUCTION (main):001:0>

And for other environments:

$ heroku run rails c –app my-development-app
Development (main):001:0>

Much better. This helps us to avoid accidentally running the wrong code in production, but what about double-checking our code as we run it in production? After all, sometimes we do need to run scripts against our live database (for instance, for zero-downtime schema changes). We’ve adopted a practice that’s become enormously helpful for us in these scenarios. First, the IRB change:

Then, how we use it in our scripts:

Giving us:

PRODUCTION (main):001:0> destroy_test_students
Destroying 904 test students.

Confirm changes? [y/N] Whoops! I was expecting to destroy only two students. Time to investigate before destroying all of these students.
No changes made.
PRODUCTION (main):002:0>

Running our changes in transactions allows us to roll them back safely, either by not confirming at the prompt or by raising an error at any point inside the block if something seems off (for instance, with a check like raise "Stop!" if students_to_destroy.length != 2 ). This lets us feel much more confident about the changes we’re making to live data.

Lastly, there’s lots of room to improve IRB’s visuals, for instance with auto-indentation ( IRB.conf[:AUTO_INDENT] = true ), syntax coloring, and whatever else you like. Here’s our entire file (so far):

Let us know if you find this useful, and we’d love to hear your own .irbrc tips and tricks!


Sound fun? We’re hiring!

Related Posts
Implementing priority lanes for jobs of the same type in Sidekiq
Ruby Gem – ExternalFields
Generating PDFs From Webpages With A Large Number Of Graphs
Our Git Workflow