rake
rake copied to clipboard
How to determine whether any prerequisite tasks needed to run at the time they were defined?
I have a use-case in which I need to run a task if and only if at least one of its prerequisite tasks either (1) currently needs to run or (2) needed to run at the time the prerequisite task was defined. Here are some attempts at a Rake::Task
subclass:
class MyTask < Rake::Task
def needed?
prerequisite_tasks.any?(&:needed?)
end
end
This approach does not work, since at the time MyTask#needed?
is called, prerequisite tasks may have run and therefore return false
for #needed?
.
class MyTask < Rake::Task
def needed?
prerequisite_tasks.any? { |p| p.needed? or p.already_invoked }
end
end
This also doesn't work, since #already_invoked
can return true
[even if the task's #execute
method was never called]:
@already_invoked = true
invoke_prerequisites(task_args, new_chain)
execute(task_args) if needed?
What ended up working was:
class MyTask < Rake::Task
def initialize(*)
@needed = false
super
end
def enhance(*)
super.tap { @needed |= prerequisite_tasks.any?(&:needed?) }
end
def needed?
@needed
end
end
But that just feels... wrong. Is there something I'm missing here? I'd be more than happy to open a PR implementing what I'm looking for (maybe an #already_executed
method?) if this functionality doesn't already exist.
Thanks!
What you require is state, and you do it well with the @needed
attribute.
Considerations:
Your description says:
The task runs if and only if
- one of its prerequisite tasks currently needs to run
- one of its prerequisite tasks needed to run at the time the prerequisite task was defined.
This could be translated to:
class MyTask < Take::Task
def needed?
prerequisite_tasks.any? do |prereq|
prereq.needed_at_def_time? || prereq.needed?
end
end
end
You can't be sure the prerequisites are of the class MyTask
. So I would add that special state to the Task
class, and also the helper method needed_at_def_time?
class Rake::Task
attr_accessor :needed_at_def_time
def enhance(*)
super
@needed_at_def_time |= needed?
end
end
No matter what happens during the executions, @needed_at_def_time == true
will dominate the control. Not big problem as already_invoked
is verified before executing, so it should not execute multiple times during 1 run. But it is important to keep that in mind for other secondary effects, like if you are using needed?
to calculate other logic by your own custom code.