簡體   English   中英

如何使兩個任務共享選項?

[英]How to make two thor tasks share options?

使用Thor,可以使用method_option設置特定任務的選項。 要為一個類中的所有任務設置選項,可以使用class_option 但是,如果有人希望班級中的某些任務而不是全部共享選項,那該怎么辦呢?

在下面的task1task2股的選擇,但它們不共享所有的選項和他們分享任何選項task3

require 'thor'

class Cli < Thor
  desc 'task1', 'Task 1'
  method_option :type, :type => :string, :required => true, :default => 'foo'
  def task1
  end

  desc 'task2', 'Task 2'
  method_option :type, :type => :string, :required => true, :default => 'foo'
  method_option :value, :type => :numeric
  def task2
  end

  desc 'task3', 'Task 3'
  method_option :verbose, :type => :boolean, :aliases => '-v'
  def task3
  end
end

Cli.start(ARGV)

與陳述的問題method_option :type, :type => :string, :required => true, :default => 'foo'兩個task1task2是,它違反了DRY原則 有沒有慣用的方式來處理這個問題?

method_option中定義thor.rb和它根據文檔采用以下參數:

  • name<Symbol>::參數的名稱。
  • options<Hash>::如下所述。

知道了這一點,你可以存儲參數method_option在一個數組, 展開陣列為單獨的參數作為method_option被調用。

require 'thor'

class Cli < Thor
  shared_options = [:type, {:type => :string, :required => true, :default => 'foo'}]

  desc 'task1', 'Task 1'
  method_option *shared_options
  def task1
  end

  desc 'task2', 'Task 2'
  method_option *shared_options
  method_option :value, :type => :numeric
  def task2
  end

  desc 'task3', 'Task 3'
  method_option :verbose, :type => :boolean, :aliases => '-v'
  def task3
  end
end

Cli.start(ARGV)

我不知道這是不是慣用的,我也不認為這是那么優雅。 仍然比違反DRY原則更好。

我只會使用這樣的超類:

require 'thor'

class CliBase < Thor
  def self.shared_options

    method_option :verbose,
                  :aliases => '-v',
                  :type => :boolean,
                  :desc => 'Verbose',
                  :default => false,
                  :required => false

  end
end

...然后子類如下:

require 'cli_base'

class Cli < CliBase
  desc 'task1', 'Task 1'
  shared_options
  def task1
  end

  desc 'task2', 'Task 2'
  shared_options
  method_option :value, :type => :numeric
  def task2
  end

  desc 'task3', 'Task 3'
  method_option :colors, :type => :boolean, :aliases => '-c'
  def task3
  end
end

Cli.start(ARGV)

因此,現在有一種不錯的干方法來執行此操作,但是可能不屬於慣用的要求,盡管我想為尋求最新答案的任何人提及它。

您可以先使用class_options設置方法之間的大多數共享選項:

module MyModule
  class Hello < Thor
    class_option :name, :desc => "name", :required => true
    class_option :greet, :desc => "greeting to use", :required => true

    desc "Hello", "Saying hello"
    def say
      puts "#{options[:greet]}, #{options[:name]}!"
    end

    desc "Say", "Saying anything"
    remove_class_option :greet
    def hello
      puts "Hello, #{options[:name]}!"
    end

    def foo
      puts "Foo, #{options[:name]}!"
    end
  end
end

最好的部分是,它適用於聲明后的所有方法。 將這些設置為required時,您可以看到第一個方法同時需要greetname ,但是sayfoo僅需要名稱。

我遇到了同樣的問題,我使用了NN的答案。 但是我發現了一些問題:

如果您想共享示例中的多個選項,則效果不是很好。 假設您要在task2和task3之間共享:value 您可以創建另一個shared_options ,也可以使用共享選項創建一個數組,然后使用shared_option名稱對其進行訪問。

這可行,但是它很冗長且難以閱讀。 我已經實現了一些小的功能,可以共享選項。

Cli < Thor  
  class << self
      def add_shared_option(name, options = {})
        @shared_options = {} if @shared_options.nil?
        @shared_options[name] =  options
      end

      def shared_options(*option_names)
        option_names.each do |option_name|
          opt =  @shared_options[option_name]
          raise "Tried to access shared option '#{option_name}' but it was not previously defined" if opt.nil?
          option option_name, opt
        end
      end
    end
    #...commands 
end

這將創建一個以選項名稱為鍵的哈希,並以“ definition”(定義,默認值等)作為值(這是一個哈希)。 此后很容易訪問。

這樣,您可以執行以下操作:

require 'thor'

class Cli < Thor

  add_shared_option :type,  :type => :string, :required => true, :default => 'foo'
  add_shared_option :value, :type => :numeric

  desc 'task1', 'Task 1'
  shared_options :type
  def task1
  end

  desc 'task2', 'Task 2'
  shared_options :type, :value
  def task2
  end

  desc 'task3', 'Task 3'
  shared_options :value
  def task3
  end
end

Cli.start(ARGV)

對我來說,它看起來更具可讀性,並且如果命令數大於3或4,則是一個很大的改進。

為了不總是鍵入“ shared_options”,您還可以這樣做:

require 'thor'

class Cli < Thor
  class << self
    private
    def shared_options!
      # list your shared options here
      method_option :opt1, type: :boolean
      method_option :opt2, type: :numeric
      # etc
    end

    # alias original desc so we can call it from inside new desc
    alias_method :orig_desc, :desc

    # redefine desc, calling original desc, and then applying shared_options!
    def desc(*args)
      orig_desc(*args)
      shared_options!
    end
  end

  desc 'task1', 'Task 1'

  def task1
  end

  desc 'task2', 'Task 2'

  def task2
  end

  desc 'task3', 'Task 3'

  def task3
  end
end

或者,如果您不希望雜技具有方法別名,則可以只定義自己的方法“ my_desc”,然后調用該方法而不是“ desc”。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM