4

我想访问 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)

我意识到我可能在这里遗漏了一些非常简单的东西。谢谢。

4

3 回答 3

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
于 2013-11-10T01:26:29.757 回答
5

Thor intends for your classes to subclass the Thor class. The Thor class then includes and extends modules allowing their methods to be class methods. If you look at the source, for example Actions.rb, you will see what I mean:

# 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

This is a common Ruby idiom that uses a mixin to define class methods (as opposed to instance methods) on its inclusor.

As an example,

[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

Now calling

Klass::Mod.act_as_class_method

results in the same error you had

NoMethodError: undefined method `act_as_class_method' for Klass::Mod:Module
from (pry):26:in `__pry__'

But if you subclass Klass and include Klass::Mod the included call back extends the ClassMethod module, letting you use the methods defined in ClassMethods as class methods

[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

This took me a while to figure out at first, so don't feel bad and no, its not that simple or obvious.

于 2013-07-25T04:59:31.263 回答
0

我自己是 Thor 的新手,但我不认为它可以独立工作。

尝试在内部创建一个 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 -?
于 2013-06-30T20:15:19.673 回答