如何使用Thor模板在范围内制作ruby变量和方法?

时间:2011-07-08 20:12:31

标签: ruby templates erb 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);
}

我需要做些什么才能将名字和dir纳入范围?我有更复杂的模板,我也需要这个功能。

2 个答案:

答案 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