Как вы создаете переменные и методы ruby ​​в области видимости с помощью шаблонов Thor?

Я пытаюсь использовать метод шаблона 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);
}

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


person iand675    schedule 08.07.2011    source источник


Ответы (2)


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

person Derick Bailey    schedule 08.07.2011
comment
Ваш ответ не решил эту проблему напрямую, но помог мне понять, что я не могу получить доступ к нужным мне значениям, потому что они не связаны в классе, а только в методе. Делая их объектными атрибутами, мы сделали свое дело. - person iand675; 09.07.2011

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

Внутри класса, которому принадлежит #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 распознаваться как подкоманды исполняемого файла.

person Julian Mann    schedule 19.02.2012