A duller knife for the production Rails console
Note: This is a re-write of a post that was lost in a blog migration. Same tool, new content. Yay!
It was a Monday like any other. I’m standing at my desk, drinking coffee, when suddenly a worrying Slack notification pops up
Oh no. I think I just ran
User.update(admin: true)instead ofuser.update(admin: true)
My heart stops, panic sets in.
We were able to recover from this situation. But it was the first time that a production console change bit hard enough to make me question everything.
So post recovery. How do we move on?
Enter - Safeconsole
I had a wild idea. What if we wrapped every console session in a database transaction?
Turns out, with Pry, it was actually quite easy!
Few hooks and a large lib file later, I had it working!
Today
Today we still use the lib file version, even after I pulled the idea out into a gem and open sourced it three years ago. There’s a few more quality of life changes I’ve added, but the basic concept still remains the exact same.
Production console, with the knife dulled a bit.
The basics
gem 'safeconsole'
Then bin/rails safeconsole instead of bin/rails console.
Every session opens inside a transaction. Do the thing, look at the result, leave. Nothing was written.
user = User.find(42)
user.update!(admin: true)
user.reload.admin
# => true
exit
# rolled back. user 42 is not an admin.
If you meant it, say so before you leave:
user.update!(admin: true)
commit
exit
The rest of the commands:
commit: set the changes in the transaction to be committed to the databasenevermind: set the changes in the transaction to be discardedrefresh: start a new transaction, discarding or committing based on your configstats: some stats on the current sessioncommands: print the commands available in your session
There’s a bit of configuration too, app name, session and command timeouts, and
a current_env override for when Rails.env says production in a staging box.
That’s all in the
README.