Search code examples
rubyrake

Why are `args` not an instance of Rake::TaskArguments when a task is run with `execute` instead of `invoke`?


In Rake, when you run a task explicitly from another task using the execute command, ie:

Rake::Task['some_task'].execute(args=[arg1, arg2])

Inside the task that is run, the args will be a regular Array. If you run a task with the invoke function, ie:

Rake::Task['some_task'].invoke(arg1, arg2)

The args command will be an instance of Rake::TaskArguments. As such, you can use methods like Rake::TaskArguments.with_defaults.

Why does this difference exist? Is there a way to ensure that the args inside a task will be an instance of Rake::TaskArguments?

Generally, it seems odd that the method of calling a tasks changes the identity of the arguments.


Solution

  • Great question and I can't find a stated reason why invoke wraps arguments as Rake::TaskArguments and execute doesn't.

    execute is called from invoke in order to do the work of the task and at that point the arguments are already wrapped up into a Rake::TaskArguments instance. That's why in "normal" usage you get a Rake::TaskArguments within your task. I'd say normal usage is with tasks specified on the command line or as dependencies. In these cases you'd have the tasks being called via invoke within rake itself.

    To ensure that the arguments in the task are always a Rake::TaskArguments instance I guess the only way is to wrap the arguments when you're using execute in your own code. E.g.

    Rake::Task['some_task'].execute(Rake::TaskArguments.new(argument_names, [arg1, arg2]))
    

    argument_names is required and is the names of the arguments the task expects. You can actually get that from the task itself Rake::Task['some_task'].arg_names. The argument position in the name array needs to match the position in the value for named arguments.

    Might be worth raising your question as an issue with the rake team : https://github.com/ruby/rake/issues