2012-03-01 72 views
1

所以我想清楚如何爲一個班級設置一些選項。 '選項'是一個散列。我想這是錯的,但爲什麼(我怎樣才能讓它流動得更好)?

1)篩選出選擇,我不想要或需要

2)設置一些實例變量在其他地方使用

3),並另設散與處理的選項@current_options 。

def initialize_options(options) 
    @whitelisted_options, @current_options = [:timestamps_offset, :destructive, :minimal_author], {} 
    n_options = options.select { |k,v| @whitelisted_options.include?(k) } 
    @current_options[:timestamps_offset] = @timestamp_offset = n_options.fetch(:timestamps_offset, 0)*(60*60*24) 
    @current_options[:destructive] = @destructive = n_options.fetch(:destructive, false) 
    @current_options[:minimal_author] = @minimal_author = n_options.fetch(:minimal_author, false) 
end 

我猜這是一個有點多,不管是什麼我通過我得到:

{:timestamps_offset=>0, :destructive=>false, :minimal_author=>false} 

當我做這行通過命令行線,它的作品,因爲我想它但不是在我的班級。那麼究竟發生了什麼,我該如何清理這些?

編輯:這實際上是從我正在使用它的類中脫離出來的,但它內部並不如此,現實中的某些事情正在發生,我現在還沒有意識到。

attr_reader:current_options是如何在類上設置的,也許需要一些修改。

EDIT2:該方法的第2行應該從@whitelisted_options

EDIT3選擇:其實原來是一些我沒有想到的......「選擇」成爲從YAML文件解析字符串......並且我正在提取符號,改變這種方式會在方法尋找符號之前找不到,例如「破壞性」vs:破壞性的,所以總是默認違約。簡而言之,我只需要在導入選項時符號化散列鍵。

回答

1

您的 @current_options被初始化爲空散列。當您將 options過濾爲參數時, @current_options中將沒有任何密鑰存在,因此 n_options將最終爲空。

然後,當您在以下行中設置@current_options時,它將始終獲取默認值(0, false, false),這就是爲什麼您的輸出總是相同的原因。

您可以通過有條件地初始化@current_options所以,這只是設置爲{}一旦解決了這個問題:

@current_options || = {}

後OP編輯:

你問題與options.select - 在Ruby 1.8中,它不返回哈希,而是一個數組。您致電fetch然後總是失敗(因爲符號不能是數組索引),所以總是返回默認值。

相反,嘗試:

n_options = options.inject({}) {|h, p| h[p[0]] = p[1] if @whitelisted_options.include? p[0]; h } 

其中p是包含每個鍵/值對的數組。

在Ruby 1.9.2中,Hash.select的行爲方式與您的預期相同。

編輯2:以下是我想接近它:

class Foo 
    @@whitelisted_options= {:timestamps_offset => 0, :destructive => false, :minimal_author =>false} 

    @@whitelisted_options.keys.each do |option| 
    define_method(option) { return @current_options[option] rescue nil} 
    end 

    def initialize_options(options) 
    @current_options = {} 
    @@whitelisted_options.each {|k, v| @current_options[k] = options[k] || v} 
    @current_options 
    end 
end 

在使用中:

f = Foo.new 
f.destructive #=> nil 
f.initialize_options(:minimal_author => true, :ignore => :lol) 
f.destructive #=> false 
f.minimal_author #=> true 
f.timestamps_offset #=> 0 
+0

我確實改變了這一點,但並沒有反映出原來的情況。 n_options是具有無效選項的選項。 – blueblank 2012-03-01 23:21:38

+0

這很接近,但實際上並未返回設置變量,即始終返回默認選項(或者我看不到它的權利)。但它很接近,給我提供了另一個線索,讓我做的事情略有不同。 – blueblank 2012-03-02 02:36:59

+0

@blueblank我的代碼在設置了'@ current_options'後返回了'@ whitelisted_options'。修正:) – andrewdotnich 2012-03-02 04:34:53

0
  1. 什麼是@whitelisted_options
  2. 如果:destructive不是options中的關鍵字,您希望發生什麼?你想要:destructive => false,還是你想要@current_options根本不提:destructive
+0

@whitelisted只是一個可用的類選項列表;基本上只接受這些選項並放棄所有其他選項,如果其他人偶然碰巧過關。 – blueblank 2012-03-01 23:19:42

+0

@destructive應該默認爲false – blueblank 2012-03-01 23:20:07

+0

@blueblank:爲什麼'@ whitelisted'是一個實例變量而不是局部變量? – 2012-03-01 23:21:43