我有一个方法,它依赖于两个文件进行输入,并产生两个或多个文件作为输出。每个输入文件和每个输出文件之间没有一对一的映射 - 该方法执行组合输入数据以生成各种输出文件的操作。
这是一个(有点人为的)例子:
class Util
def self.perform
`cat source1.txt source2.txt > target1.txt`
`cat source2.txt source1.txt > target2.txt`
end
end
编辑:我的案例中的实际代码比这复杂得多,将生成每个目标文件的工作分成不同的部分是不可行的。因此,在我的情况下,每个目标文件设置一个文件任务实际上并不是一个选项。
如何在需要时设置一次rake任务以运行此方法,即。如果缺少一个或多个目标文件,或者任何源文件是否比任何目标文件更新?
我目前的解决方案如下:
task :my_task => ['source1.txt', 'source2.txt'] do |t|
targets = ['target1.txt', 'target2.txt']
if targets.all? { |f| File.exist? f }
mtime_newest_source = t.prerequisites.map {|f| File.mtime(f) }.max
mtime_oldest_target = targets.map {|f| File.mtime(f) }.min
# Stop task early if all targets are up to date
next if mtime_newest_source < mtime_oldest_target
end
# Code that actually produces target files goes here
end
我正在寻找的是一种定义任务的方法,以便没有任何代码 除非需要重建目标文件,否则将在其块中运行。
答案 0 :(得分:4)
FileTasks就是为此而设计的。这是一个good old long explanation,这是一个简单的例子:
file 'target1.txt' => ['source1.txt', 'source2.txt'] do
# do something to generate target1.txt
`cat source1.txt source2.txt > target1.txt`
end
file 'target2.txt' => ['source1.txt', 'source2.txt'] do
# again, generate the file
`cat source2.txt source1.txt > target2.txt`
end
文件任务可能依赖于磁盘上的其他rake任务或文件。如果您的任务取决于文件,则rake将比较时间戳,并且仅在相关文件较新时才运行您的任务。
这是从两个任务生成所有目标的工作示例。当第一个任务创建两个文件时,Rake非常聪明,可以跳过第二个任务。
def make_the_targets
`cat source1.txt source2.txt > target1.txt`
`cat source2.txt source1.txt > target2.txt`
end
file 'target1.txt' => ['source1.txt', 'source2.txt'] do
puts "making target1.txt"
make_the_targets
end
file 'target2.txt' => ['source1.txt', 'source2.txt'] do
puts "making target2.txt"
make_the_targets
end
task :make_targets => ['target1.txt', 'target2.txt']
答案 1 :(得分:0)
我不相信上述答案是正确的。 Lars的评论
['target1.txt', 'target2.txt'].each {
|target| file target => ['source1.txt', 'source2.txt'] { do_stuff_here }
}
如果调用rake { do stuff here }
,则会运行'target1.txt', 'target2.txt'
两次。
我相信
可以正确解决依赖关系问题 file 'target1.txt' => ['source1.txt', 'source2.txt'] { do_stuff_here }
file 'target2.txt' => 'target1.txt'