rake 命名空间与 ruby 模块

rake namespace vs. ruby module

如何在不同的 rake 任务中使用同名的辅助函数?以下代码不起作用:

# bar.rake
namespace :bar do

  desc 'bar'
  task :bar => :environment do
    bar
  end

  def bar
    puts "bar bar"
  end

end

# foo.rake
namespace :foo do

  desc 'bar'
  task :bar => :environment do
    bar
  end

  def bar
    puts "foo bar"
  end

end

(错误的)结果是:

$ rake bar:bar
foo bar

这是因为 rake 的命名空间不像 ruby 的模块那样工作,所以第二个任务中的 bar 函数重新定义了第一个任务的 bar 函数。

那么在 rake 任务中使用本地辅助函数的好的解决方案是什么?

更多的是风格偏好,但通常我会用静态方法创建一个Task class(或者如果你需要管理一些状态,则构建一个实例)并在rake任务中使用它们.这样,这些方法也很容易测试。你的情况:

namespace :bar do
  task :bar => :environment do
    StaticTask.fetch
  end
end

# OR

namespace :foo do
  task :bar => :environment do
    idea = AnotherIdea.new
    idea.fetch
  end
end

更多的是我个人喜欢遵循的模式,但它在任务之间创建了一个很好的关注点分离。

(这对 require 也很重要,无论你带来什么 class)

您可以将整个定义包装在一个模块中,但您需要使用 Rake DSL 对其进行扩展:

# bar.rake
Module.new do
  extend Rake::DSL

  namespace :bar do

    desc 'bar'
    task :bar => :environment do
      bar
    end

    def self.bar
      puts "bar bar"
    end

  end

# foo.rake
Module.new do
  extend Rake::DSL

  namespace :foo do

    desc 'bar'
    task :bar => :environment do
      bar
    end

    def self.bar
      puts "foo bar"
    end

  end
end

另一种使用本地辅助函数的方法是使用 本地 辅助函数:)

namespace :bar do

  desc 'bar'
  task :bar => :environment do
    helper = -> {
      puts 'bar bar'
    }

    helper.call
  end

end