LoginSignup
0
1

More than 5 years have passed since last update.

モジュールやクラスの中から Rake の DSL 構文を使う

Last updated at Posted at 2016-05-16

Rake タスクが複雑になりかけていたので、分割してモジュールに収めることにした。

環境

  • Rake 10.5.0
  • Ruby 2.2.3

失敗例

とりあえず、タスク定義をそのまま特異メソッドの中に移してみる。

module TaskHelper
  def self.add_default()
    task :default do
      puts "ok"
    end
  end
end

TaskHelper.add_default

しかしこれはエラー。

$ rake
rake aborted!
NoMethodError: undefined method `task' for TaskHelper:Module

なぜ

探してみると Rake の DSL 定義は lib/rake/rake/dsl_definition.rb の最下部にあった。

lib/rake/dsl_definition.rb
module Rake
  module DSL

    ...

    def task(*args, &block)
      Rake::Task.define_task(*args, &block)
    end

    ...

  end
end

self.extend Rake::DSL

一番外側の self に extend している。先ほどのエラーは、モジュール内モジュールが、モジュール名を付けずに外側のメソッドを使えないのと同じ理由だろうか。

task 等の機能はグローバルな関数として定義されているものだと思い込んでいた。

def task(*args, &block)
  Rake::Task.define_task(*args, &block)
end

module TaskHelper
  def self.add_default()
    task :default do
      puts "ok"
    end
  end
end

TaskHelper.add_default

これだと動く。

ただし、現実の定義は違う。

解決策

仕組みがわかれば簡単。

Rake の機能を使いたいモジュールやクラスに Rake::DSL を取り込めばいい。

module TaskHelper
  extend Rake::DSL

  def self.add_default()
    task :default do
      puts "ok"
    end
  end
end

TaskHelper.add_default
$ rake
ok

特異メソッドではなくインスタンスのメソッドとして使う場合は include を使用する。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1