One way to do this is to use bundler to scaffold our gem:
bundler gem my_gem
I prefer to put tasks meant to manage the gem itself in lib/tasks
, and tasks the gem is meant to provide to gem users in lib/my_gem/tasks
.
I also follow the following rules when writing Rake tasks:
- One task per file
- File name should match the task name exactly and have a
.rake
extension - Tasks should be namespaced
- Files should be in a directory whose name matches the task namespace
So, say our gem is called my_gem and adds the tasks foo:a
, foo:b
, and bar:c
. Our directory structure would look something like this:
my_gem
└── bin
└── ...
└── lib
└── my_gem
└── tasks
└── foo
├── a.rake
├── b.rake
└── bar
├── c.rake
├── Rakefile
├── railtie.rb
├── helper.rb
├── ...
├── my_gem.rb
└── ...
Use Rails::Railtie
to have all rake tasks automatically loaded when this gem is required in a Rails app.
railtie.rb
(seen in directory structure above), at a minimum, would look something like this:
# lib/railtie.rb
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
Then, in my_gem.rb
aka the file loaded when our gem is required, we’d want something like:
# lib/my_gem.rb
module MyGem
require 'my_gem/railtie' if defined?(Rails)
end
Integrate our gem with plain old Ruby projects
Provide a Rakefile
that gem users can load into their Rakefiles:
# lib/Rakefile
require 'my_gem'
path = File.expand_path(__dir__)
Dir.glob("#{path}/tasks/**/*.rake").each { |f| import f }
Rails
In the project Rakefile
, at some point before Rails.application.load_tasks
is run, be sure to require my_gem
, whether that be through Bundler.require(*Rails.groups)
, require 'my_gem'
, or whatever.
Make sure that the new code is actually being run e.g. restart spring if that’s been running.
In the project Rakefile
, load my_gem‘s
Rakefile:
require 'my_gem'
spec = Gem::Specification.find_by_name 'my_gem'
rakefile = "#{spec.gem_dir}/lib/my_gem/Rakefile"
load rakefile
From command line
rake -T -A
Rake.application.tasks.map(&:to_s)
===========
source: http://mdzhang.com/blog/code/2016/09/10/create-ruby-gem-that-adds-rake-tasks/