2012-10-12 33 views
0

所以,這是我到目前爲止有:你如何定義一個帶「。」的方法擴展了先前存在的屬性的功能?

# @return [Array<Hash>] of variables ([Placeholders, actual variables]) 
    def variables 
     # @return [Hash] of all variables. 
     #  If actual variables are named teh same as the placeholders, the placeholders will be over written. 
     #  This implementation of merging hashes of an array will work even if we add more elements to the 
     #  variables array. 
     self.class.send(:define_method, "variables.flatten") do 
     return self.variables.inject{|placeholders, vars| placeholders.merge(vars || {})} 
     end 

    return [placeholder_variables, self.variable_data] 
    end 

我希望能夠做到:

my_object.variables # => return the Array<Hash> 

而且還能夠做到

my_object.variables.flatten # => return a single merged hash 

的問題時,我只是做

def variables.flatten 

是,當我運行控制檯,我得到一個錯誤信息說variables沒有定義(或只是不管我.flatten前放)

是有辦法,我只能定義在variables屬性我的自定義.flatten方法? (正常<Array>.flatten在這裏不工作,因爲我需要合併散列。)

+0

crea是一個專門的課程。看不到另一個優雅的選項 – apneadiving

回答

1

直接的答案:它自己的模塊中定義的方法,那麼它包含數組中返回:

module SpecialFlatten 
    def flatten 
    first.update last 
    end 
end 

......後來......

def variables 
    vals = [placeholder_variables, self.variable_data] 
    return vals.extend(SpecialFlatten) 
end 

但在這種情況下,更好的選擇可能是這樣做的:

def variables(*flags) 
    if flags.include? :flatten 
    placeholder_variables.update self.variable_data 
    else 
    [placeholder_variables, self.variable_data] 
    end 
end 
0

我不認爲有可能定義「variables.flatten」方法。通過這個例子證明,讓我們來看看:

require 'ruby_parser' 

RubyParser.new.parse(<<-EOF) 
    my_object.variables.flatten 
EOF 
#=> s(:call, 
s(:call, s(:call, nil, :my_object, s(:arglist)), :variables, s(:arglist)), 
:flatten, 
s(:arglist)) 

正如你可以看到variablesflatten是不同的記號,他們不能合併成一個記號,這是一個解析問題。

但是有一件事可能你錯過了 - 這就是可鏈接性。方法variables返回變量數組,如果它們響應平展方法,結果將是平坦的。如果他們沒有迴應該方法,則應該爲這些對象實施flatten方法。

+0

用RubyParser的優秀插圖 –

+0

當然,可以定義該方法。 OP的代碼就是這樣做的。 –

0

您可以在返回的值上定義一個單例方法。

def variables 
    result = [placeholder_variables, self.variable_data] 
    # redefine method flatten on the result array 
    def result.flatten 
    # did not understand what you are trying to do here 
    # self is the array here 
    inject{|placeholders, vars| placeholders.merge(vars || {})} 
    end 
    return result # return the array with added method 
end 

但是,這幾乎總是一個壞主意。

0

Array#flatten方法是Ruby核心的一部分,所以我建議不要更改它,特別是如果您正在與其他開發人員一起開發團隊。看起來你正在努力符合現有的界面。我會尋找替代方法,但是您可以覆蓋variables方法的返回值上的平展方法。

def variables 
    [placeholder_variables, self.class.variable_data].tap do |vars| 
    vars.instance_eval do 
     def flatten 
     inject{|result, vars_hash| result.merge!(vars_hash)} 
     end 
    end 
    end 
end 
+0

[placeholder_variables,self.class。variable_data]已經是一個數組了,我認爲flatten方法應該爲數組中的每個元素定義,如果他們沒有響應它的話。 – megas

+0

@megas,你所描述的只有在OP想要做一些像'variables.map(&:flatten)'這樣的東西時纔會起作用。相反,OP真的想重寫'#flatten'來做一個合併數組(Hash實例)所有元素的注入。例如。如果#variables返回'[{a:1},{b:2},{c:3}]',那麼對該結果調用#flatten應該返回'{a:1,b:2,c:3}'。 –