Как сделать переменные и методы ruby ​​в области видимости с помощью шаблонов Thor? - PullRequest
1 голос
/ 09 июля 2011

Я пытаюсь использовать метод шаблона Thor :: Actions для генерации некоторых шаблонов тестовых файлов C ++, но erb постоянно говорит мне, что у меня есть неопределенные переменные и методы.*

def test (name, dir)
  template "tasks/templates/new_test_file", "src/#{dir}/test/#{name}Test.cpp"
  insert_into_file "src/#{dir}/test/CMakeLists.txt", 
       "#{dir}/test/#{name}Test ", :after => "set(Local "
end

Вот шаблон:

<% test_name = name + "Test" %>
#include <gtest/gtest.h>
#include "<%= dir %>/<%= name %>.h"

class <%= test_name %> : public testing::Test {
protected:
    <%= test_name %> () {}
    ~<%= test_name %> () {}
    virtual void SetUp () {}
    virtual void TearDown () {}
};

// Don't forget to write your tests before you write your implementation!
TEST_F (<%= test_name %>, Sample) {
   ASSERT_EQ(1 + 1, 3);
}

Что мне нужно сделать, чтобы получить здесь имя и директорию?У меня есть более сложные шаблоны, для которых мне тоже нужна эта функциональность.

Ответы [ 2 ]

4 голосов
/ 19 февраля 2012

Я понимаю, что вы уже решили эту проблему, но я публикую этот ответ на тот случай, если кто-то другой найдет решение вашего вопроса (как было I ).

Внутри класса, к которому принадлежит #test, создайте attr_accessor, а затем установите его значение в том же методе, который вызывает шаблон.

class MyGenerator < Thor

  attr_accessor :name, :dir

  def test (name, dir)
    self.name = name
    self.dir = dir
    template "tasks/templates/new_test_file", "src/#{dir}/test/#{name}Test.cpp"
  end
end

Примечание: если вы объединяете методы с помощью #invoke, то для каждого вызова будет использоваться новый экземпляр класса. Поэтому вы должны установить переменную экземпляра в методе с помощью вызова шаблона. Например, следующее не будет работать.

class MyGenerator < Thor

  attr_accessor :name

  def one (name)
    self.name = name
    invoke :two
  end

  def two (name)
    # by the time we get here, this is another instance of MyGenerator, so @name is empty
    template "tasks/templates/new_test_file", "src/#{name}Test.cpp"
  end

end

Вы должны поместить self.name = name внутрь #two вместо

Для создания генераторов, если вы вместо этого наследуете от Thor :: Group, все методы вызываются по порядку, и attr_accessor будет настроен для вас с переменными экземпляра, установленными для каждого метода. В моем случае мне пришлось использовать Invocations вместо Thor :: Group, потому что я не мог распознать классы Thor :: Group как подкоманды исполняемого файла.

2 голосов
/ 09 июля 2011

ERB использует объект привязки ruby ​​для получения переменных, которые вы хотите. Каждый объект в ruby ​​имеет привязку, но по умолчанию доступ к привязке ограничен самим объектом. вы можете обойти это и передать желаемую привязку в шаблон ERB, создав модуль, который предоставляет привязку объекта, например:

module GetBinding
  def get_binding
    binding
  end
end

Затем вам нужно расширить любой объект, у которого есть переменные, которые вы хотите с этим модулем.

something.extend GetBinding

и передать привязку этого объекта в erb

something.extend GetBinding
some_binding = something.get_binding

erb = ERB.new template
output = erb.result(some_binding)

Полный пример работы с ERB приведен на этой вики-странице одного из моих проектов: https://github.com/derickbailey/Albacore/wiki/Custom-Tasks

...