Как я могу вызывать методы Rake из модуля

В моих rake-файлах есть много служебных функций, некоторые из которых создают rake-таски. Я хочу переместить эти служебные функции в модуль, чтобы избежать конфликтов имен, но когда я это сделаю, методы rake больше не будут доступны.

require 'rake'

directory 'exampledir1'

module RakeUtilityFunctions
    module_function
    def createdirtask dirname
        directory dirname
    end
end

['test1', 'test2', 'test3'].each { |dirname|
    RakeUtilityFunctions::createdirtask dirname
}

Ошибка, которую я получаю:

$ rake
rake aborted!
undefined method `directory' for RakeUtilityFunctions:Module
C:/dev/rakefile.rb:8:in `createdirtask'
C:/dev/rakefile.rb:13:in `block in <top (required)>'
C:/dev/rakefile.rb:12:in `each'
C:/dev/rakefile.rb:12:in `<top (required)>'

Насколько я могу судить, метод каталога размещен на верхнем уровне ruby ​​с помощью следующий код в Rake:

# Extend the main object with the DSL commands. This allows top-level
# calls to task, etc. to work from a Rakefile without polluting the
# object inheritance tree.
self.extend Rake::DSL

Есть ли простой способ вызова функций, которые были размещены на верхнем уровне, как это?


person Eoghan    schedule 07.09.2015    source источник


Ответы (2)


Когда вы определяете модуль, код внутри этого модуля имеет новую область действия.

Таким образом, directory в RakeUtilityFunctions находится в другой области действия, чем код верхнего уровня.

Поскольку вы не определили directory в RakeUtilityFunctions, вы получите ошибку неопределенного метода.

Взгляните на раздел Scope Gate этой статьи.

person ReggieB    schedule 09.09.2015
comment
Спасибо за ответ @ReggieB. С вашей помощью нашел еще один вопрос по похожей проблеме, смотрите мой ответ. - person Eoghan; 09.09.2015

Я понял это сейчас. С помощью @ReggieB я обнаружил этот вопрос: способы определения глобального метод в ruby.

Он содержал выдержку из журнала изменений рейка.

Если вам нужно вызвать 'task :xzy' внутри вашего класса, включите в класс Rake::DSL.

Итак, самый простой способ сделать это — расширить модуль с помощью Rake::DSL:

require 'rake'

directory 'exampledir1'

module RakeUtilityFunctions
    self.extend Rake::DSL     ### This line fixes the problem!
    module_function

    def createdirtask dirname
        directory dirname
    end
end

['test1', 'test2', 'test3'].each { |dirname|
    RakeUtilityFunctions.createdirtask dirname
}
person Eoghan    schedule 09.09.2015