ruby - 限制命名空间内定义的规则范围
问题描述
我有以下 Rakefile(这是一个简化的示例):
namespace :green do
rule(/^build:/) do |t|
puts "[green] #{t}"
end
task :start do
puts '[green] start'
end
task run: ['build:app', :start]
end
namespace :blue do
rule(/^build:/) do |t|
puts "[blue] #{t}"
end
task :start do
puts '[blue] start'
end
task run: ['build:app', :start]
end
我希望每个“构建”规则仅适用于定义它的命名空间。换句话说,这就是我想要发生的事情:
$ rake blue:run
[blue] build:app
[blue] start
但实际发生的是这样的(使用 Rake 12.3.1):
$ rake blue:run
[green] build:app
[blue] start
有没有办法限制“构建”规则的范围,以便无法从“蓝色”命名空间访问“绿色”命名空间中定义的规则?
解决方案
看起来 Rake 本身并不支持这一点。任务的范围限定在它们定义的命名空间中(通过添加范围路径作为前缀),但规则没有这样的前缀。
我能够通过猴子修补 Rake 来使其工作,这并不理想:
# Monkey-patch rake
module Rake
module TaskManager
# Copied from rake 12.3.1 and enhanced for scoped rules
def lookup_in_scope(name, scope)
loop do
tn = scope.path_with_task_name(name)
task = @tasks[tn]
return task if task
break if scope.empty?
# BEGIN ADDED LINES
task = enhance_with_matching_rule(tn)
return task if task
# END ADDED LINES
scope = scope.tail
end
nil
end
end
module DSL
# Create a rule inside a namespace scope
def scoped_rule(name, &block)
pattern = "^#{Rake.application.current_scope.path}:#{name}:"
Rake.application.create_rule(Regexp.new(pattern), &block)
end
end
end
namespace :green do
scoped_rule :build do |t|
puts t
end
task :start do |t|
puts t
end
task run: ['build:app', :start]
end
namespace :blue do
scoped_rule :build do |t|
puts t
end
task :start do |t|
puts t
end
task run: ['build:app', :start]
end
输出:
$ rake green:run
green:build:app
green:start
$ rake blue:run
blue:build:app
blue:start