When working in the Rails console, I tend to build up commands over time that I run often. These might be for resetting data, fetching something from an API, generating tokens, etc. Multiple times a day, I find myself holding down the up arrow on the keyboard until I find the last time I ran it, so I can run it again. Usually, there will be multiple commands that need to be run in sequence, which get concatenated together with semi-colons so they can all be run in one go. I don't know for sure, but I imagine every developer does this.
As an example, right now I'm working on a project that calls a large number of API endpoints on various different microservices. These all require authentication via a JWT token. We use Her (an ORM for making requests to REST APIs and representing their responses with Ruby classes and objects). We have some Faraday middleware that adds the JWT token (stored in RequestLocals) to the Authorization header to authenticate the requests with the microservices. This means that when I am testing these API calls in the Rails console, I need to fetch a JWT and store it in RequestLocals.
That means running this same command a few dozen times throughout each day, and holding down the up arrow on my keyboard to find it each time:
RequestLocals.store[:jwt] = JWT.create(user_id: 'USER_ID_HERE').jwt
After a while, I got tired of doing this and started looking for a better way. I wondered if I could add global helper methods to the Rails console to perform common tasks. Turns out that you can!
First, open up
config/application.rb and add this:
module MyRailsApp class Application < Rails::Application # Add custom global helper methods to the console. console do # Use this if you use IRB (the default Rails console). Rails::ConsoleMethods.include(ConsoleMethods) # Use this if you use Pry. # See https://blog.nhocki.com/2015/06/03/add-helper-methods-to-your-rails-console-with-pry/ for more information. TOPLEVEL_BINDING.eval('self').extend(ConsoleMethods) end end end
Then create a new file called
app/lib/console_methods.rb and add your method. Here's my method for the JWT scenario as an example, although obviously, you can place any method that you want here:
module ConsoleMethods def load_jwt! token = ::JWT.create(user_id: 'USER_ID_HERE') RequestLocals.store[:jwt] = token.jwt end end
Restart your console and now you can run
load_jwt! almost as if it were a built-in Rails console command/method, similar to
Note regarding reloading:
It is possible that you might find your custom commands not working after running
reload!, and see an error along these lines:
ArgumentError: A copy of ConsoleMethods has been removed from the module tree but is still active! from /Users/glen/.rvm/gems/ruby-2.4.3@acuit-nexthub-ui/gems/activesupport-5.1.3/lib/active_support/dependencies.rb:495:in `load_missing_constant'
In a future post we will dive deeper into how Rails automatically loads and reloads constants (e.g. classes), as that is complex enough to require its own post. In the meantime, simply prepend
:: to the constant that you're referencing (e.g.
::User instead of
It's a small thing, but adding these custom methods to the console has cut out a lot of repetition from my days. Reducing some of those longer lines that I run often to just invoking a method has already saved me a lot of time. If you have any of these lines that you find and run often in the console, then this trick should improve your productivity as it did for me.