Alias of Task Name in Rake

Alias of task name in Rake

Why do you need an alias? You may introduce a new task without any code, but with a prerequisite to the original task.

namespace :db do
task :table do
puts "table"
end
#kind of alias
task :t => :table
end

This can be combined with parameters:

require 'rake'
desc 'My original task'
task :original_task, [:par1, :par2] do |t, args|
puts "#{t}: #{args.inspect}"
end

#Alias task.
#Parameters are send to prerequisites, if the keys are identic.
task :alias_task, [:par1, :par2] => :original_task

To avoid to search for the parameters names you may read the parameters with arg_names:

#You can get the parameters of the original 
task :alias_task2, *Rake.application[:original_task].arg_names, :needs => :original_task

Combine it to a define_alias_task-method:

def define_alias_task(alias_task, original)
desc "Alias #{original}"
task alias_task, *Rake.application[original].arg_names, :needs => original
end
define_alias_task(:alias_task3, :original_task)

Tested with ruby 1.9.1 and rake-0.8.7.

Hmmm, well, I see that's more or less exactly the same solution RyanTM already posted some hours ago.

Get rake task name in initializer

None of the other answers presented here will work unless you stop using Spring, because Spring changes the way rake tasks are called significantly.

When using Spring, the command being run is handed over to the Spring server process using a UNIX socket and unfortunately Spring server reads this socket to get the command and its arguments after initializing the rails environment. Thus, during rails initialization, there seems to be no way of getting the command and its arguments (e.g. the rake task name) when using Spring, as Spring itself does not know yet! Even the after_fork hook that Spring provides won't help, because it is being also run after rails initialization.

A proof can be seen in the Spring source code. It is the serve method in which Spring gets the ARGV of the command being run from the socket, forks itself and runs the command. The relevant parts of the method are these:

def serve(client)
# ... getting standard input / output streams from the client socket

# this is where rails initialization occurs
preload unless preloaded?

# this is where Spring gets the command name and it's ARGV and environment
args, env = JSON.load(client.read(client.gets.to_i)).values_at("args", "env")
command = Spring.command(args.shift)

# ...

# fork and run the command
pid = fork {
# ...
# run the command
ARGV.replace(args)
$0 = command.exec_name
# ...

# run the after_fork hook
invoke_after_fork_callbacks

command.call
}

# ...
end

The rails initializers are run in the preload method which is run before the command name is read from the socket. The $0 and ARGV variables are also set after initialization, in the fork block.

So, unless you monkey-patched Spring significantly (replaced the serve method with your own, but you'd need to handle working with the socket yourself), you need to stop calling your rake tasks inside the Spring environment. If the rake command is a binstub in the RAILS_ROOT/bin/ directory, you need to remove the binstub with spring binstup --remove rake.

Only then, I believe, you can use one of the solutions in the other answers.

Default task for namespace in Rake

Place it outside the namespace like this:

namespace :my_tasks do
task :foo do
do_something
end

task :bar do
do_something_else
end

end

task :all => ["my_tasks:foo", "my_tasks:bar"]

Also... if your tasks require arguments then:

namespace :my_tasks do
task :foo, :arg1, :arg2 do |t, args|
do_something
end

task :bar, :arg1, :arg2 do |t, args|
do_something_else
end

end

task :my_tasks, :arg1, :arg2 do |t, args|
Rake::Task["my_tasks:foo"].invoke( args.arg1, args.arg2 )
Rake::Task["my_tasks:bar"].invoke( args.arg1, args.arg2 )
end

Notice how in the 2nd example you can call the task the same name as the namespace, ie 'my_tasks'

How do I stop rake from treating a file dependency as a possible task name?

I observe the same behavior. The FileTask, as defined by the file method in the rake DSL, inherits from the main Rake Task class and, indeed, invoking the dependencies (or in Rake's language prerequisities) seems to be the same for Tasks as well as FileTasks, i.e. if a file name is already defined as a rake task, the task is run instead.

The only solution that comes to my mind is to add the path part to the files in FILES_TO_INCLUDE. It can be anything as simple as a "./" prefix.

So, I'd try this instead:

file 'output.zip' => FILES_TO_INCLUDE.map { |file| "./#{file}" } do
...
end

This approach seems to work OK for me.

Also, for your particular scenario (creating a zip file of some other files), you can actually use a ready-made solution already present in Rake, the PackageTask:

Rake::PackageTask.new("rake", "1.2.3") do |p|
p.need_zip = true
p.package_files.include("lib/**/*.rb")
end

This will create a rake-1.2.3.zip archive in the pkg (configurable) subdirectory. You probably will also need to prefix the files with some directory specification.

Is there a way to know the current rake task?

I'm thinking of making an app behave different when runned by rake.

Is it already enough to check caller, if it is called from rake, or do you need also which task?


I hope, it is ok, when you can modify the rakefile. I have a version which introduce Rake.application.current_task.

# Rakefile
require 'rake'
module Rake
class Application
attr_accessor :current_task
end
class Task
alias :old_execute :execute
def execute(args=nil)
Rake.application.current_task = @name
old_execute(args)
end
end #class Task
end #module Rake

task :start => :install do; end
task :install => :install2 do
MyApp.new.some_method()
end
task :install2 do; end

# myapp.rb
class MyApp
def some_method(opts={})
## current_task? -> Rake.application.current_task
puts "#{self.class}##{__method__} called from task #{Rake.application.current_task}"
end
end

Two remarks on it:

  • you may add the rake-modifications in a file and require it in your rakefile.
  • the tasks start and install are test tasks to test, if there are more then one task.
  • I made only small tests on side effects. I could imagine there are problems in a real productive situation.


Related Topics



Leave a reply



Submit