Too much Repition
The situation: lots of projects, and you’ve got important code to share. Except in this case, your code are rake tasks for devops, and you can’t just throw it into a module within a gem and have it run properly. Sharing rake tasks via a gem is slightly more complex than sharing module or code classes with a gem, so read on to see how I made it happen.
DRY Your Projects
In an earlier post (Rails 5 Base Application) I mentioned a recent uptick in the number of new projects I’ve started which has finally brought me to the point that I’ve established some common processes and started to extract them where possible. One component of my basic application are some custom rake tasks I use for heroku deploys and database backups. On rare occassions, I want something minor changed in that task. In the past, that means I’ll go and copy past the updated code around 3 or 4 active projects. Now, with that list rapidly growing, I need a way to have shared code amongst all my projects. Time to bring Bundler and RubyGems up to bat.
Gem Creation and Sharing Your Code
What follows are some basic steps to extract
rake my_task:talk which is shared among applications into a local gem repository to share among your apps.
First, some basic steps to get a gem up and running (for local dev, I won’t go into publishing it here):
mkdir rake_gem cd rake_gem bundle init
This leaves you with a skeleton to get you going and a few prompted customization options. Now, to the good stuff.
Code and Structure
The below snippets assume you’re still in the
#./lib/tasks/my_task namespace :my_task desc 'Say something' task :talk puts "Something." end end
Now, since the above is in
lib/tasks rather the gem directory, you have to make sure it’s both included in your code, and also available to Rails when it’s included as a gem. We’ll solve this problem in reverse. What’s needed is a Railtie so that way Rails (and therefore rake) is aware of the task. Besides just the documentation, Andy Atkinson has an older but succinct rundown of part of the process which you may find helpful.
#./lib/rake_gem/railtie.rb class RakeGem::Railtie < Rails::Railtie rake_tasks do load 'tasks/my_task.rake' end end
Finally, make sure your Railtie is included in your gem.
#./lib/rake_gem.rb require "rake_gem/version" require "rake_gem/railtie" if defined?(Rails) module RakeGem end
At this point, you can test it out locally. Go to your rails app and add the following to your
gem 'rake_gem', path: "~/rake_gem"
Bundle install to ensure Bundler’s happy with your gem then testing it will give you the following:
bundle install bundle exec rake my_task:talk Something
That’s all there is to it. You can now publish this gem or just use it locally for testing; whatever suits your needs. I try to keep these examples as succinct as possible to prevent getting stuck in the weeds and to showcase the MVP version of functionality.
If you enjoy having free time and the peace of mind that a professional is on your side, then you’d love to have me work on your project.