[英]How to make two thor tasks share options?
使用Thor,可以使用method_option
設置特定任務的選項。 要為一個類中的所有任務設置選項,可以使用class_option
。 但是,如果有人希望班級中的某些任務而不是全部共享選項,那該怎么辦呢?
在下面的task1
和task2
股的選擇,但它們不共享所有的選項和他們分享任何選項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'
兩個task1
和task2
是,它違反了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時,您可以看到第一個方法同時需要greet和name ,但是say和foo僅需要名稱。
我遇到了同樣的問題,我使用了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.