14

Is it possible to call a task which is defined in a Rakefile - not in somefile.rake - from an other Ruby script?

I was hoping that creating a new Rake::Application would automatically load the Rakefile from the same directory, but it seems that this is not the case. Here is what I came up with so far:

$LOAD_PATH.unshift File.dirname(__FILE__)
require 'rake'
require 'pp'

rake = Rake::Application.new
rake[:hello].invoke

Executing this code results in the following:

/opt/ruby/1.9.2-p180/lib/ruby/1.9.1/rake.rb:1720:in `[]': Don't know how to build task 'hello' (RuntimeError)
from script.rb:7:in `<main>'

pp rake yields the following:

#<Rake::Application:0x00000101118da0
 @default_loader=#<Rake::DefaultLoader:0x00000101118b20>,
 @imported=[],
 @last_description=nil,
 @loaders=
  {".rb"=>#<Rake::DefaultLoader:0x00000101118a80>,
   ".rf"=>#<Rake::DefaultLoader:0x000001011189b8>,
   ".rake"=>#<Rake::DefaultLoader:0x00000101118800>},
 @name="rake",
 @original_dir=
  "/Users/t6d/Projects/Sandbox/Ruby/rake-from-ruby-script",
 @pending_imports=[],
 @rakefile=nil,
 @rakefiles=["rakefile", "Rakefile", "rakefile.rb", "Rakefile.rb"],
 @rules=[],
 @scope=[],
 @tasks={},
 @top_level_tasks=[],
 @tty_output=false>

It is somehow irritating that @rakefile is nil.

Update May 20th, 4:40pm CET

After reading the rake source code for a little while, I figured out that you need to call Rake::Application#init in order to initialize your newly created rake application:

rake = Rake::Application.new
rake.init
rake.load_rakefile

However, I still cannot invoke any tasks defined in my Rakefile:

rake.top_level_tasks # => ["default"]

I'd gladly appreciate any help on that matter.

2
  • 1
    See stackoverflow.com/questions/3530/… too Commented Sep 19, 2011 at 9:13
  • FWIW, that link tells how to run one task, by constructing the application, the script will behave more like the rake executable.
    – Smar
    Commented Feb 2, 2015 at 12:25

2 Answers 2

18
+50

You forgot to add your new rake to the current Rake Application:

$LOAD_PATH.unshift File.dirname(__FILE__)

require 'rake'
require 'pp'

rake = Rake::Application.new
Rake.application = rake
rake.init
rake.load_rakefile

rake[:hello].invoke

or just

$LOAD_PATH.unshift File.dirname(__FILE__)
require 'rake'
require 'pp'

Rake.application.init
Rake.application.load_rakefile

Rake.application[:hello].invoke
2
  • Genius and right on time. I was starting to think that I might have to use something like system rake ..., but now I can use this much cleaner solution of yours. Thanks a lot!
    – t6d
    Commented May 21, 2011 at 15:06
  • Great solution, though it needs modifying slightly to support tasks with arguments. See my answer here: stackoverflow.com/questions/13858495/…
    – KomodoDave
    Commented Dec 13, 2012 at 12:48
11

Just load the Rakefile:

==> foo.rb <==
require 'rubygems'
require 'rake'

load 'Rakefile'

Rake::Task[:some_task].invoke

==> Rakefile <==
task :some_task do
  puts "some_task"
end

Rake::Application is all about command-line processing, default rakefiles, output, etc. You might not need any of that.

1
  • Thanks, this solved my problem. I assumed the Rakefile would be loaded by default in Rails but it's not.
    – Venkat D.
    Commented Aug 16, 2012 at 19:55

Not the answer you're looking for? Browse other questions tagged or ask your own question.