Thor desc 中的变量

Variable in Thor desc

对于 cli 项目,我希望与 thor 任务共享一个超级 class。当调用子命令帮助时,它应该公开带有自定义描述的共享命令。

我想出了下面的代码,但是在描述中没有替换变量@plural。

Thor 和一些元编程可能吗?

module MyModule
  class ResourceSubcommand < Thor

    def initialize(*args)
      super
    end

    desc "list", "list all #{@plural}"
    def list
      list_object(@default_list_columns)
    end
  end
end

module MyModule
  class Account < MyModule::ResourceSubcommand

    def initialize(*args)
      super
      @plural = 'accounts'
    end

  end
end

module MyModule
  class Commands < Thor

    desc "account SUBCOMMAND ...ARGS", "manage Exact Online accounts"
    subcommand "account", Account

  end
end

运行 $ thorcli account help 应该输出:

Commands:
  thorcli account help [COMMAND]     # Describe subcommands or one specific subcommand
  thorcli account list               # list all accounts

传递给desc的字符串是在class的上下文中计算的,但是initialize方法是在上下文中计算的 个实例 ,因此两个 @plural 属于两个不同的对象。

此外,desc在定义superclassMyModule::ResourceSubcommand时立即被调用,并且在superclass得到之后没有简单的方法来推迟它的评估inherited 并且设置了子class中的@plural,你的目标似乎很难实现。

P.S。我尝试覆盖 MyModule::ResourceSubcommand::inheritedMyModule::ResourceSubcommand.singleton_class::inherited,但我失败了。也许您可以将 MyModule::ResourceSubcommand 定义为一个模块,覆盖它的 self.included,并在子 class 中 after 设置 @plural 包含它。

更新

我终于成功了。这是我的解决方案:

module MyModule

  # Change from class to module
  module ResourceSubcommand

    # A hook called when this module is included by other modules
    def self.included(base)
      base.class_eval do
        desc "list", "list all #{@plural}"
        def list
          list_object(@default_list_columns)
        end
      end
    end
  end
end

module MyModule

  # No inheritance
  class Account

    # Don't put this in any instance methods, including #initialize
    @plural = 'accounts'

    # Be sure to include after @plural is set
    include ResourceSubcommand
  end
end