2010-06-30 28 views
3

我正試圖在Ruby和ActiveRecord中爲多態對象實現責任鏈模式。我遇到一些問題。Ruby中的責任鏈和alias_method問題

  • 有時我,當我嘗試alias_method它的方法是沒有定義的錯誤,我想這是因爲沒有加載類或東西,所以我明確地做一個發送拿到方法
  • 我得到了一堆無限鏈,其中別名函數(original_method)調用了調用original_method的方法。我想知道這是否是因爲當你別名一個已被覆蓋的方法時,你實質上是將「original_method」作爲別名方法的副本。
  • 我目前正在通過像「chained」這樣的函數返回Setting中的一個子類來定義所有已定義的方法,但好奇爲什麼alias_method在類中存在這麼多問題。

下面是一個例子:

class Hospital 
    has_one :setting, :as => :settable 
    belongs_to :administrative_area 

    def next_link 
    adminstrative_area 
    end 

    def usable_setting 
    setting ? setting : next_link.usable_setting 
    end 
end 

然後,我有一個設置對象:

class Setting < ActiveRecord::Base 

belongs_to :settable, :polymorphic => true 

def chained 
    %w(api_key active_days).each do |method| 

    # this is here because otherwise the method isn't defined, 
    # it's almost as while it's going up, the metaclass doesn't have the columns 
    # until it loads, probably will be fixed if we cache classes 
    self.send method.to_sym 

    (class << self; self; end).class_eval do 

     define_method method do |*args| 
     alias_method "original_#{method}", method 
     my_setting = send("original_#{method}") 
     if my_setting.nil? or my_setting.empty? 
      settable.next_link.usable_setting.chained.send(method) 
     else 
      return my_setting 
     end 
     end 
    end 
    end 
    self 
end 
end 

回答

1

你似乎過於複雜。似乎你正試圖查看api_key和active_days是否存在,如果不存在,從其他地方獲取它。

這裏是做正確的方式,假設API_KEY和active_days在你的表列:

class Setting < ActiveRecord::Base 

    belongs_to :settable, :polymorphic => true 

    def api_key 
    super || settable.next_link.usable_setting.api_key 
    end 

    def active_days 
    super || settable.next_link.usable_setting.active_days 
    end 
end 

你可以重構它一下,以保持透明度和消除重複。

class Setting < ActiveRecord::Base 

    belongs_to :settable, :polymorphic => true 

    def api_key 
    super || next_usable_setting.api_key 
    end 

    def active_days 
    super || next_usable_setting.active_days 
    end 

    private 
    def next_usable_setting 
    settable.next_link.usable_setting 
    end 
end 

所以在這種情況下請注意 - 如果您有api_key/active_days可用,它將返回。 Otehrwise,它會從next_link取得可用的設置。如果那個人有api_key/active_days,它會被返回,否則它會從next_link中獲取useful_setting。等等

+0

嘿,這個答案很好,但我認爲我所遇到的主要問題是在定義方法的metamagically。我想這樣做的原因是我有很多鏈接功能,作爲程序員寧願花10個小時計算出如何避免打字,而不是2個小時,只需輸入全部英寸。 我最終做了它通過創建一個代表鏈接的獨立類,我認爲在主動記錄中很難做到這一點,因爲它創建了自己的別名函數。 – David 2010-07-08 15:40:32

+0

如果你想神奇地做到這一點,你所要做的就是:'[:api_key,:active_days] .each {| meth | define_method(meth){super || next_usable_setting.send(甲基)}}'。但坦率地說,我寧願單獨定義它們,因爲它讀起來更好。 – 2010-07-08 21:02:19