Including Rake Tasks in Gems

Including rake tasks in gems

On Rails 3, you do this via Railties. Here's the code to do it for a gem I just made:

class BackupTask < Rails::Railtie
rake_tasks do
Dir[File.join(File.dirname(__FILE__),'tasks/*.rake')].each { |f| load f }
end
end

So you basically create a class that inherits from Rails::Railtie, then within that class you have a rake_tasks block that loads the relevant files. You must load instead of require if you want to use a .rake extension.

I found that I need to specify the full path to Dir (hence the File.join gymnastics). If I just wanted to list the file explicitly then I could get away with just saying load 'tasks/foo.rake' because the /lib dir of my gem was in the load path.

Requiring a gem inside a gem's rake task

Here is what I did to make it work:

tasks.rake

require 'database_cleaner'
require 'dummy_tasks'

namespace :db do
task :dummy => :environment do
DatabaseCleaner.strategy = :truncation
DatabaseCleaner.clean
Rake::Task['db:seed'].invoke
end
end

There may be a more elegant way to do this, but this should at least prevent you from having to add the database_cleaner gem to the app Gemfile

Running gems rake tasks from application rake tasks

so there are several things to be taken into consideration here.

for the record, this is how you call a task with arguments

Rake::Task["taskname"].execute(args)

in your case, i did not realize first, that it actually uses environment variables instead of task arguments that are read as ENV['CLASS'].

that would answer your question, so you can either set it ENV['CLASS'] = 'ClassName' or pass it along to your call to the rake task rake geolocal CLASS=ProposedAccomodation.

which brings me to a following question: why are you not just calling the original rake task, there is nothing you add to it.

Local rake tasks require development gems to be in production group

Maybe not the most exciting answer but I just moved the require 'dev_gem' inside the rake task block for that task.

namespace :elasticbeanstalk do
desc 'Creates a new web & worker environment pair for testing'
task :create do
require 'aws-sdk-elasticbeanstalk'

# Do stuff with beanstalk that we wouldn't from a production env
end
end

This way the library only gets loaded when the rake task is invoked rather than when the rake task is defined.

Why is this gem not adding rake tasks to a Rails app?

The problem was not with the gem, but with the way it was included in the app.

In the Gemfile, this works and includes the rake task:

gem 'gem_fresh'

This works but doesn't include the rake task:

group :development do
gem 'gem_fresh'
end

This seems to be due to how Bundler requires gems in Rails apps. From the documentation:

By default, a Rails generated app calls Bundler.require(:default, Rails.env) in your application.rb, which links the groups in your Gemfile to the Rails environment.

If for some reason that Rails.env argument wasn't evaluating to include the :development group, which seems to be the case when I call rake -T, the gem wouldn't be Bundler.require-d, and the rake tasks wouldn't be loaded.

The fact that it isn't including the :development group seems to be an odd Bundler "gotcha", but at least now I know that moving it to the default group solves the issue and it's not a problem with the gem.

Ruby Rake load tasks from a gem

Okay, I found a solution for this problem if anyone is interested:

# Rails.root/Rakefile

spec = Gem::Specification.find_by_name 'test'
load "#{spec.gem_dir}/tasks/deploy.rake"

That's all I needed to say in my Rakefile!

Rake tasks inside gem not being found

Fixed it on my end. In the gemspec, you need to include the rake tasks files as well, not just the lib files:

Instead of:

  s.files = Dir['lib/**/*.rb']

Use:

  s.files = Dir['lib/**/*.rb'] + Dir['tasks/*.rake']

rails rake task with globally installed gem

If you do want to load a gem without having it in your Gemfile you can do the following in your rake task:

$: << '/Users/<user>/.rvm/rubies/ruby- 
x.x.x/lib/ruby/gems/x.x.x/gems/smarter_csv-x.x.x/lib'
require 'smarter_csv'

I think the option to have the gem in your Gemfile with the require: false option is more suitable however. The gem won't be loaded until you specifically require it.

Load rake tasks from ruby gem

I've just restarted spring and new rake tasks appeared in my rake -T list. :)



Related Topics



Leave a reply



Submit