我正在尝试使用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);
}
我需要做些什么才能将名字和dir纳入范围?我有更复杂的模板,我也需要这个功能。
答案 0 :(得分:4)
我意识到你已经解决了这个问题,但是我发布了这个答案,以防其他人出现寻找你问的问题的解决方案(如我那样)。
在#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类识别为可执行文件的子命令。
答案 1 :(得分: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的完整示例,请参阅我的某个项目的此Wiki页面:https://github.com/derickbailey/Albacore/wiki/Custom-Tasks