1 min read

A Gem that Provides Rake Tasks

I'm building a Gem and I want it to provide Rake tasks when it is used in other projects
A Gem that Provides Rake Tasks
Photo by Rasa Kasparaviciene / Unsplash

I'm building a Gem and I want it to provide Rake tasks when it is used in other projects.

I'm going to create a separate .rake file for each of tasks I want to expose. These will be in a folder named after the namespace I want to use. I'm also going to create a Rakefile inside my gem which will expose these to the client (I might have another Rakefile which contains the tasks I'm using during the development of the gem but I don't want to expose these to the client).

I'm going to have a namespace called foobar and two tasks, first and second. This way I can use the tasks by calling rake foobar:first etc. I'm going to use this directory structure:

.
└── lib
    ├── my_gem
    │   ├── tasks
    │   │   └── foobar
    │   │       ├── first.rake
    │   │       └── second.rake
    │   └── Rakefile
    └── my_gem.rb

The Rakefile contains the following:

require 'my_gem'

path = File.expand_path(__dir__)
Dir.glob("#{path}/tasks/**/*.rake").each { |f| import f }

and my .rake files look like:

namespace :foobar do
  
  desc "Say hello"
  task :hello do
    puts "Hello world"
  end
end

Using the tasks in a ruby project

To use these tasks in another plain-old-ruby project, that project needs to include this in it's Rakefile:

require 'my_gem'

spec = Gem::Specification.find_by_name 'my_gem'
rakefile = "#{spec.gem_dir}/lib/my_gem/Rakefile"
load rakefile

Using the tasks in a Rails project

To play nicely with Rails, our my_gem can provide a railtie. This should live in lib/my_gem.

require 'my_gem'
require 'rails'

module MyGem
  class Railtie < Rails::Railtie
    railtie_name :my_gem

    rake_tasks do
      path = File.expand_path(__dir__)
      Dir.glob("#{path}/tasks/**/*.rake").each { |f| load f }
    end
  end
end

and the my_gem.rb should be modified to include the loading of the railtie:

module MyGem
  require 'my_gem/railtie' if defined?(Rails)
end