2016-05-29 50 views
1

方法一起我有一個模塊Settings類似如下:實現「=」用的method_missing

module Settings 
    extend self 

    @_settings = {user: "user1"} #@_seetings would normally be filled with different (dynamic) options 
    attr_reader :_settings 

    def method_missing(name, *args, &block) 
    @_settings.has_key?(name.to_sym) ? @_settings[name.to_sym] : 
     raise(NoMethodError, "unknown configuration root #{name}", caller) 
    end 
end 

在我的應用程序可以使用Settings.user訪問選項user

現在我想這樣做像這樣Settings.user = "some_user"

我試着補充一點:

def method_missing=(name, *args, &block) 
    #some code to assign the value 
end 

不幸的是,這是行不通的。 (unknown configuration root user= (NoMethodError))。什麼是「正確」的方式來做到這一點?

回答

2

方法名稱something=引用一個不存在的方法仍然會被method_missing捕獲。

您可能想要修改method_missing以查看名稱是否以'='結尾並相應地執行。

這就是說,如果你說Settings.method_name,那麼你的Settings模塊上調用一個方法,而不是包含該模塊的實例。

此外,模塊不包含狀態;這是區分他們與類的事物之一。另外,您是否確定要覆蓋包含類的method_missing方法(或者如果類的方法正常,則忽略它)?

你能解釋一下爲什麼你使用這個模塊嗎?也許你會想要定義一個類,並在它的類中包含它的一個實例(組合而不是繼承)?

+0

該應用程序是一個cli工具。 Settings模塊分析命令行選項並將它們提供給應用程序。它不被繼承或包含在其他類/模塊中。這只是必需的。 –

+0

我認爲你使用的模塊方法增加了*方法*比所需的更復雜。您可能可以爲此使用「OpenStruct」。在http://ruby-doc.org/stdlib-2.0.0/libdoc/ostruct/rdoc/OpenStruct.html查看。我一直使用這個命令行選項。 –

0

簡短的回答是,你不能在Ruby中覆蓋=,覆蓋這些類型的操作符被認爲是危險的。有關更多詳細信息,請參閱this answer

但是,這個確切的用例很好地被ruby處理。你有兩個選擇:

def user= (some_object) 
    @_settings = {user: some_object} 
end 

或使用戶的Setting屬性和使用attr_accessor

module Settings 
    attr_accessor :user 
    def new(user) 
    @user = user 
    end 
end 

就快與attr_reader它是attr_accessor一半,另一半是attr_writer。看看這個其他的SO thread