Namespaces in Ruby Rake Tasks - ruby

Are the following equivalent?
namespace :resque do
task setup: :environment do
end
end
task "resque:setup" => :environment do
end

In short: yes. When running rake resque:setup both of these tasks will be invoked.
Rake will merge these tasks. You can test this by doing the following:
p Rake.application.tasks
Which in this case would return something like
[<Rake::Task resque:setup => [environment]>]
Which is simply an Array holding a single Rake::Task object. You can also check the scope or list of namespaces for a task by doing:
p Rake.application.tasks.first.scope
#=> ["resque"]
If you want to learn a little more on how the internals of Rake work, check out Rake::Task and Rake::TaskManager

Related

Can I catch errors and continue to next Rake task?

I invoke Rake tasks in another Rake task like following:
namespace :test do
task :migrate do
Rake::Task['A:migrate'].invoke
Rake::Task['B:migrate'].invoke
end
end
What I want to know is whether I can continue to the next Rake task even if the earlier one fails. For instance, there is an error in A:migrate, I want to catch it and log it but move ahead with B:migrate. How can I do this?
Rake is just Ruby, so you can use Ruby's error handling feature.
namespace :test do
task :migrate do
begin
Rake::Task['A:migrate'].invoke
rescue => e
log(e)
end
Rake::Task['B:migrate'].invoke
end
end

Modify Rake Task at test/runtime

Consider the following
class Foo
def bar
1
end
end
And then two rake tasks ...
task :something
InvokeSomething(Foo.new)
end
task :test
do_some_testing
end
def do_some_testing
setup_test
`rake something`
check_if_it_did_everything_correctly
end
After executing setup_test, I want to modify the source for class Foo to return 2 for method bar.
Ideas:
Create a rake task that gets invoked before I define the rake task something and I modify the source code directly. So that something is defined with a different source code.
Somehow modify the Rake task so that that particular method is overridden. At the very least I need a reference to the rake task during runtime.
There are multiple ways to do this.
You can get the reference from Rake::Task["something"] during do_some_testing and re-define a method there.
But there is another even simpler way - which worked for me. Set the value in bar as an environment variable. And modify the environment variable when needed.

Confused with the second variable of task : some_random_name1, [:some_random_name2] => :environment in rake?

I am new to ruby and rake, and currently confused with some ruby syntax.
task :some_random_name1, [:some_random_name2] => :environment do |task, args|
end
What does [:some_random_name2] here mean? I know some_random_name1 is a task that depends on another task :environment, and task and args in |task, args| are arguments from command line. Thanks in advance.
[:some_random_name2] is referring to arguments that you can pass into your rake task. May I suggest checking out this article which can explain in more depth passing arguments to a rake task.
When you call rake -T from the command line, you should see:
rake example: some_random_name1[some_random_name2]
(assuming your namespace is 'example')

Run rake tasks in sequence

I have rake tasks which i want to run in proper sequence.
I want to run one rake task which run other rake tasks in proper sequence.
How may i do that?
you should consider defining dependencies between your tasks like this
task :primary => [:secondary]
task :secondary do
puts "Doing Secondary Task"
end
But if you really, really need to call the tasks directly you can use invoke to call another task
task :primary do
Rake::Task[:secondary].invoke
end
task :secondary do
puts "Doing Secondary Task"
end
see also here

How do I run Rake tasks within a Ruby script?

I have a Rakefile with a Rake task that I would normally call from the command line:
rake blog:post Title
I'd like to write a Ruby script that calls that Rake task multiple times, but the only solution I see is shelling out using `` (backticks) or system.
What's the right way to do this?
from timocracy.com:
require 'rake'
def capture_stdout
s = StringIO.new
oldstdout = $stdout
$stdout = s
yield
s.string
ensure
$stdout = oldstdout
end
Rake.application.rake_require 'metric_fetcher', ['../../lib/tasks']
results = capture_stdout {Rake.application['metric_fetcher'].invoke}
This works with Rake version 10.0.3:
require 'rake'
app = Rake.application
app.init
# do this as many times as needed
app.add_import 'some/other/file.rake'
# this loads the Rakefile and other imports
app.load_rakefile
app['sometask'].invoke
As knut said, use reenable if you want to invoke multiple times.
You can use invoke and reenable to execute the task a second time.
Your example call rake blog:post Title seems to have a parameter. This parameter can be used as a parameter in invoke:
Example:
require 'rake'
task 'mytask', :title do |tsk, args|
p "called #{tsk} (#{args[:title]})"
end
Rake.application['mytask'].invoke('one')
Rake.application['mytask'].reenable
Rake.application['mytask'].invoke('two')
Please replace mytask with blog:post and instead the task definition you can require your rakefile.
This solution will write the result to stdout - but you did not mention, that you want to suppress output.
Interesting experiment:
You can call the reenable also inside the task definition. This allows a task to reenable himself.
Example:
require 'rake'
task 'mytask', :title do |tsk, args|
p "called #{tsk} (#{args[:title]})"
tsk.reenable #<-- HERE
end
Rake.application['mytask'].invoke('one')
Rake.application['mytask'].invoke('two')
The result (tested with rake 10.4.2):
"called mytask (one)"
"called mytask (two)"
In a script with Rails loaded (e.g. rails runner script.rb)
def rake(*tasks)
tasks.each do |task|
Rake.application[task].tap(&:invoke).tap(&:reenable)
end
end
rake('db:migrate', 'cache:clear', 'cache:warmup')

Resources