我想要访问Thor :: Actions(http://textmate.rubyforge.org/thor/Thor/Actions.html)有一些很好的帮助方法,但如果不使用Thor CLI应用程序我似乎无法使用它们。
我试过简单:
require "rubygems"
require "thor"
Thor::Actions.create_file "foo.txt", "contents"
引发:
run.rb:4:in '<main>': undefined method 'create_file' for Thor::Actions:Module (NoMethodError)
我意识到我可能会遗漏一些非常简单的东西。感谢。
答案 0 :(得分:5)
Thor打算让你的类继承Thor类。然后Thor类包含并扩展模块,允许它们的方法成为类方法。如果您查看来源,例如Actions.rb
,您会看到我的意思:
# thor/lib/thor/actions.rb
class Thor
module Actions
# this is the interesting part and answers your question
def self.included(base) #:nodoc:
base.extend ClassMethods
end
module ClassMethods
这是一个常见的Ruby习惯用法,它使用mixin在其包含器上定义类方法(而不是实例方法)。
举个例子,
[2] pry(main)> class Klass
[2] pry(main)* module Mod
[2] pry(main)* def self.included(base)
[2] pry(main)* base.extend ClassMethods
[2] pry(main)* end
[2] pry(main)* module ClassMethods
[2] pry(main)* def act_as_class_method
[2] pry(main)* puts "Im a class method now!!!"
[2] pry(main)* end
[2] pry(main)* end
[2] pry(main)* end
[2] pry(main)* end
=> nil
现在致电
Klass::Mod.act_as_class_method
会导致您遇到同样的错误
NoMethodError: undefined method `act_as_class_method' for Klass::Mod:Module
from (pry):26:in `__pry__'
但是,如果您将Klass
和include Klass::Mod
子类化为included
回调extends
ClassMethod
模块,则允许您使用ClassMethods
中定义的方法作为类方法
[4] pry(main)> class Example < Klass
[4] pry(main)* include Klass::Mod
[4] pry(main)* self.act_as_class_method
[4] pry(main)* end
=> Im a class method now!!!
=> nil
这让我花了一些时间来弄清楚,所以不要感到难过,不要,它不是那么简单或明显。
答案 1 :(得分:5)
在不继承Thor::Actions
的情况下使用Thor
:
class Builder # or whatever
# To get your hands on the `from_superclass` method
include Thor::Base
# What we're interested in…
include Thor::Actions
source_root "/path/to/where/things/come/out"
def initialize(*)
# whatever you might want to do
@destination_stack = [self.class.source_root]
end
end
希望别人觉得这很有用。用Thor v0.18.1进行测试和测试;因为这是内部API的东西,它可能会在未来的某个时刻打破。
然后,您可以在Builder
类中使用辅助方法,如下所示:
class Builder
def build
in_root { 'do things' }
create_file 'etc'
end
end
修改:如果您想控制创建文件和文件夹的位置,则需要设置destination_root
,如下所示:
class Builder
include Thor::Base
include Thor::Actions
source_root Dir.pwd
def initialize(root)
self.destination_root = File.expand_path(root)
end
def build
directory 'templates', 'target'
end
end
答案 2 :(得分:0)
我自己是托尔的新手,但我不认为它是独立工作的。
尝试在内部创建一个Thor任务,然后启动它。
这是我尝试过的一个例子,放在一个名为thor_createfile.rb
的文件中(我已经提出了一些其他的东西,我会在代码之后解释一下,这可能对你很有启发性):
#!/usr/bin/env ruby
require 'rubygems'
require 'thor'
class MyThorTasks < Thor
include Thor::Actions
default_task :createInflexibleFile
desc "createFile <fname> <content>", "Creates a file with some content"
def createFile(fname, content)
create_file fname, content
end
INFLEXIBLE_FILENAME = "the_filename.txt"
INFLEXIBLE_CONTENT = "Greetings, Earthlings!"
desc "createInflexibleFile", "Creates a file called '#{INFLEXIBLE_FILENAME}' containing '#{INFLEXIBLE_CONTENT}'"
def createInflexibleFile
puts "Creating a file called '#{INFLEXIBLE_FILENAME}' containing '#{INFLEXIBLE_CONTENT}'"
create_file INFLEXIBLE_FILENAME, INFLEXIBLE_CONTENT
end
end
MyThorTasks.start
您可以看到它定义了一个扩展Thor
的类,然后在其上调用start
方法。
现在你应该能够像这样调用它:
./thor_createfile.rb
它将使用指定为default_task
的任务。
但是如果您需要获取一些命令行参数,则可以按名称显式调用任务。所以要调用其他任务,例如:
./thor_createfile.rb createFile fancy_file_name.txt "Text to go inside the file"
注意我已将其告知include Thor::Actions
,因此您感兴趣的所有项目(例如create_file
)都可用。
现在你可以在其中添加其他任务(确保为每个任务添加desc
或者它可能会抱怨)并根据需要使用它们。
要让它告诉你里面定义的所有任务,你可以这样称呼它:
./thor_createfile.rb -?