2014-03-30 14 views
1

在試圖開發一個簡單的寶石學的過程中,我正好絆倒在這個問題上:雷神 DSL使用語法發生在選項命令option :some_option, :type => :boolean ,就在方法定義之前。動態加載雷神選項一個Ruby寶石

我想從文件中加載一組動態選項。我在構造函數中執行了這個文件讀取操作,但是看起來option關鍵字Thor類在initialize方法之前正在處理。

任何想法來解決這個問題?如果有人能解釋option關鍵字是如何工作的,那麼它會很好。我的意思是option一個方法調用?我沒有得到設計。 (這是我想出來的第一DSL和是一個總新手紅寶石寶石)

#!/usr/bin/env ruby 

require 'thor' 
require 'yaml' 
require 'tinynews' 

class TinyNewsCLI < Thor 
    attr_reader :sources 
    @sources = {} 

    def initialize *args 
    super 
    f = File.open("sources.yml", "r").read 
    @sources = YAML::load(f) 
    end 

    desc "list", "Lists the available news feeds." 
    def list 
    puts "List of news feed sources: " 
    @sources.each do |symbol, source| 
     puts "- #{source[:title]}" 
    end 
    end 

    desc "show --source SOURCE", "Show news from SOURCE feed" 
    option :source, :required => true 
    def show 
    if options[:source] 
     TinyNews.print_to_cli(options[:source].to_sym) 
    end 
    end 

    desc "tinynews --NEWS_SOURCE", "Show news for NEWS_SOURCE" 
    @sources.keys.each do |source_symbol| # ERROR: States that @sources.keys is nil 
    #[:hindu, :cnn, :bbc].each do |source_symbol| # I expected the above to work like this 
    option source_symbol, :type => :boolean 
    end 
    def news_from_option 
    p @sources.keys 
    TinyNews.print_to_cli(options.keys.last.to_sym) 
    end 

    default_task :news_from_option 

end 

TinyNewsCLI.start(ARGV) 

回答

3

一個略微調整之後,我覺得我在一個解決方案,看起來並不太壞結束。但不確定如何將代碼放在模塊中是一種很好的做法。但無論如何:

#!/usr/bin/env ruby 

require 'thor' 
require 'yaml' 
require 'tinynews' 


module TinyNews 

    # ***** SOLUTION ******* 
    f = File.open("../sources.yml", "r").read 
    SOURCES = YAML::load(f) 

    class TinyNewsCLI < Thor 

    default_task :news_from_source 

    desc "list", "Lists the available news feeds." 
    def list 
     puts "List of news feed sources: " 
     SOURCES.each do |symbol, source| 
     puts "- #{source[:title]}" 
     end 
    end 

    desc "--source NEWS_SOURCE", "Show news for NEWS_SOURCE" 
    option :source, :required => true, :aliases => :s 
    def news_from_source 
     TinyNews.print_to_cli(options[:source].to_sym) 
    end 
    end 

end 

TinyNews::TinyNewsCLI.start(ARGV)