2013-01-15 9 views
7

थोर एक विशेष कार्य के विकल्प सेट करने के लिए 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) 

task1 और task2 दोनों के लिए method_option :type, :type => :string, :required => true, :default => 'foo' बताते हुए के साथ समस्या यह है कि यह the DRY principle का उल्लंघन करता है। क्या इसे संभालने का एक बेवकूफ तरीका है?

उत्तर

11

method_optionthor.rb में परिभाषित किया गया है और यह प्रलेखन के अनुसार निम्नलिखित मानकों लेता है:

  • name<Symbol>:: तर्क का नाम है।
  • options<Hash>:: नीचे वर्णित।

यह जानते हुए कि यह आप method_option के रूप में एक सरणी में method_option और expand that array into separate parameters पैरामीटर स्टोर कर सकते हैं कहा जाता है।

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 सिद्धांत का उल्लंघन करने से बेहतर है।

+1

अच्छा विचार है, लेकिन क्या हम आगे बढ़ सकते हैं और शायद guarant_option + को आम हैश को विलय करने के लिए साझा_ऑप्शन क्लास विधि को परिभाषित कर सकते हैं? – inger

3

मैं सिर्फ इस तरह एक सुपर क्लास का प्रयोग करेंगे:

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) 
+0

क्या आपको वास्तव में यहां उप-वर्गीकरण की आवश्यकता है? क्यों सीएलआई कक्षा में साझा_ऑप्शन परिभाषित नहीं? – inger

+3

मुझे लगता है कि ओपी का जवाब देने के कई तरीके हैं। मैं अपने समाधान के साथ एक से अधिक बार लेखन कोड को तुच्छ मानता हूं, बेस क्लास लिखता हूं, इसे एक मणि में डालता हूं और फिर जब भी एक और थोर स्क्रिप्ट लिखता हूं तो इसका उपयोग करता हूं। आखिरकार, वर्बोज़ के लिए -v कुछ ऐसा है जो मैं एक उदाहरण के बाहर फिर से उपयोग करूंगा। लेकिन यकीन है कि, हालांकि आप इसे पसंद कर सकते हैं। – Midwire

2

मैं एक ही समस्या थी और मैं क्या N.N. इस्तेमाल किया जवाब दे दिया। लेकिन मुझे कुछ समस्याएं मिलीं:

यदि आप उदाहरण में एक से अधिक विकल्प साझा करना चाहते हैं, तो यह बहुत अच्छा काम नहीं करता है। कल्पना करें कि आप task2 और task3 के बीच :value साझा करना चाहते हैं। आप एक और shared_options बना सकते हैं या आप साझा विकल्पों के साथ एक सरणी बना सकते हैं और इसे साझा_पशन नाम से एक्सेस कर सकते हैं।

यह काम करता है लेकिन यह वर्बोज़ और पढ़ने के लिए मुश्किल है। मैंने विकल्प साझा करने में सक्षम होने के लिए कुछ छोटा सा कार्यान्वित किया है।

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 

इस कुंजी के रूप में विकल्प के नाम के साथ एक हैश, और मूल्य के रूप में 'परिभाषा' (अपेक्षित, डिफ़ॉल्ट, आदि) (जो एक हैश है) पैदा करता है। यह बाद में आसानी से सुलभ है।

इस के साथ, आप निम्न कर सकते हैं:

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 है यह एक महान सुधार है।

0

तो जैसा कि "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 "के बजाय कॉल करें।

संबंधित मुद्दे