Ruby Rake Load Tasks from a 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!

Load rake tasks from ruby gem

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

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.

How do I import rake tasks from a gem when using Sinatra?

I figured out how to do it after 10+ hours of trying to figure it out and I had to patch Rake in the process. I submitted this patch:
https://github.com/jimweirich/rake/pull/28

I also wrote up a blog entry that contains the patched code:
http://www.justinidea.com/2011/03/proposed-modification-to-rakes-discovery-of-tasks.html

[UPDATE]

I also found another way that doesn't require a rake patch, go figure...all I had to do was create a tasks.rb and require it inside the rakefile, but to make this work I had to make it look like this:

require 'rake'
require 'bundler'
Bundler.setup
require 'orientdb'
require 'orientdb/tasks'

I still think the rake patch is pretty cool though. :)

[UPDATE 2]

In the mean time until the pull request gets accepted by the rake team, I created a gem called alltasks that will load all of the rake tasks that the gems in your Gemfile and their dependencies contain.

https://github.com/ricaurte/alltasks

Ruby: Accessing rake task from a gem without Rails

I found the body of the solution here. I've modified it to support specification of tasks with arguments and added support for cucumber.

So..

Within your gem create bin/my_gem

Paste the script at bottom of this post into it. See comments for example usage.

Your rake tasks must be in your Rakefile.

Alternatively, add your tasks e.g. to lib/tasks/*.rake then add the following into your Rakefile:

Dir.glob('lib/tasks/*.rake').each {|r| import r}

Here's the secret sauce:

#!/usr/bin/env ruby

# Run rake tasks and cucumber features
# from my_gem once it's installed.
#
# Example:
#
# my_gem rake some-task
# my_gem rake some-task[args]
# my_gem cucumber feature1 feature2
#
# Note: cucumber features have '.feature' appended automatically,
# no need for you to do it ;)
#
# Author:: N David Brown
gem_dir = File.expand_path("..",File.dirname(__FILE__))
$LOAD_PATH.unshift gem_dir# Look in gem directory for resources first.
exec_type = ARGV[0]
if exec_type == 'rake' then
require 'rake'
require 'pp'
pwd=Dir.pwd
Dir.chdir(gem_dir) # We'll load rakefile from the gem's dir.
Rake.application.init
Rake.application.load_rakefile
Dir.chdir(pwd) # Revert to original pwd for any path args passed to task.
Rake.application.invoke_task(ARGV[1])
elsif exec_type == 'cucumber' then
require 'cucumber'
features = ARGV[1,].map{|feature| "#{gem_dir}/features/#{feature}.feature"}.join(' ')
runtime = Cucumber::Runtime.new
runtime.load_programming_language('rb')
pwd=Dir.pwd
Dir.chdir(gem_dir) # We'll load features from the gem's dir.
Cucumber::Cli::Main.new([features]).execute!(runtime)
Dir.chdir(pwd) # Revert to original pwd for convenience.
end

Bingo! :-)

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.

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.

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.



Related Topics



Leave a reply



Submit