What Automation Can Do For You: Rake in Ruby on Rails
“To err is human[…]” — Alexander Pope
Humans have evolved since the dawn of computers — so much so that some philosophers have argued that we are basically androids now because we have Google machines in our pockets. We might not realize it, but our smartphones can also help us automate our lives. We can have daily alerts from news sources, remind ourselves of events in our calendar, and even set an alarm to wake us up in the morning.
Why is this useful? As humans, we tend to be forgetful. When we tell our phones to reminds us of these things, we are ensuring that we don’t forget whatever it is we need to do. We are freeing up headspace in order to deal with more complex problems. How can we apply these tenets to programming? Enter Rake.
What is Rake?
Rake is a library of code that allows you to automate tasks by simply installing the gem. You can then put your tasks in a Rakefile
, and run the commands with the term rake
from the command line. Your file might look something like this:
In order to call the first task, we would input rake time
in the command line and get back :
Rake tasks typically consist of three parts: the task name, the block that the task executes, and the description. The task
name declares the name that calls the task in the command line, any tasks that are dependent on that task, and any variables that need to be passed in. The block contains the code that the task will run when it is called from the command line. Rake tasks are written in ruby, so Ruby code needs to go in the block. The description displays what the task is meant to do in plain English. Desc
s are optional but highly recommended for better readability.
In order to see what tasks are available to us, we can use the command rake -T
Here’s a simple list of the tasks we’ve written, how they need to be input into the command line, and a description of what they do. Descriptions are exceptionally useful here. You might also notice that the namespace
block can arrange our tasks into sections. In the case above, we’d have to enter our task exactly as shown rake file_creation:make_file[name_of_your_file]
where we’d enter what our file name needs to be in between the [].
Rake and Rails
Rake is also integrated into Rails. If you’ve worked with Rails before, you probably recognize the commands rails db:migrate
or rails db:seed
. These commands are actually rake commands that come from the ActiveRecord gem, and because of the integration in rails, we can use either word to start the command. If we were to run rake -T
in a rails file, we’d get something like this:
Whoa!!! All these tasks come from the many gems that are in the Rails bundle. These tasks might seem overwhelming, but they should actually make you feel relieved. These tasks represent all the stuff the computer can do FOR you. That means you don’t have to worry too much about HOW these tasks work, as long as you know that they work. All that headspace is free to worry about more important things.
Customizing Rake
As seen above, gems can come with rake tasks built into them. These gems usually run in the command line with commands specific to the gem, but the documentation will usually list the rake task and how to implement it into your Rakefile
. Let’s look at an example.
Here we are running 3 different gems through Rake commands. Brakeman tests your code for security vulnerabilities. Rubocop makes sure your code follows the Ruby style guide. Reek checks your code for ‘code smell’ and keeps it DRY. If I wanted to check my build every time I finished a feature or file, I’d have to run each of their respective rake commands. What if it’s 2 A.M. and I forget to run one? Let’s pack them all into one command.
First, I established a namespace
called test_build
to place them all under. I then looked at the documentation for each gem to find their implementation of their rake task. Each task has specific options you can pass into to customize the way the gem behaves. The two most important ones here are the exit and output options.
All 3 gems will exit the terminal as soon as they have finished running, so we need to change their exit behavior. Each gem is different, but since ruby is very readable, we can simply look for the words “fail” or “exit” to find the option we need.
Since each gem has an option to output errors to separate files, we can organize them in our dev folder using FileUtils. FileUtils is a module that’s included with Rake, and allows us to write Ruby code to manipulate our file structure. In the final task, we first delete the folder holding the error files, the brakeman task makes a “TODO” folder and places the error file in it, and finally we move the Reek and Rubocop error files into the “TODO” folder.
Voila! We now have one rake task we can run that takes care of all the logic for us. While running three commands might seem easier, each time we test our build we might forget a task or what options to pass it. We’d then need to take time looking it up, which might throw off our workflow or even worse, push code with a security vulnerability. We can take comfort in the fact that our pre-established task runs 100% correctly, 100% of the time.