2011-01-20 48 views
1

我有一個簡單的acts_as風格模塊,包含在ActiveRecord :: Base中。該模塊的目的是:無法調用缺少方法內的關聯。幫幫我!

  1. 添加HAS_ONE關聯ActiveRecord模型

  2. 添加缺失的方法的情況下,這將直接任何缺少方法到相關的背景。

這裏的例子模塊:

module TestModule 

    def self.included(base) 
    base.send :extend, ClassMethods 
    end 

    module ClassMethods 

    def test_me_out 
     has_one :text_page 
     send(:include, InstanceMethods) 
    end 

    end 

    module InstanceMethods 

    def method_missing(method, *args, &block) 
     Rails.logger.debug "#{method}" 
     #text_page.send(method, *args, &block) 
     text_page 
    end 

    end 
end 

而且我可能會使用它在AR模型的方式...

Class Page < ActiveRecord::Base 
    test_me_out 
end 

的問題是,如果*的method_missing *模塊中的方法運行時,會立即導致method_missing內出現「堆棧級別太深」的錯誤....

app/lib/test_module.rb:24:in `method_missing' 
    app/lib/test_module.rb:24:in `method_missing' 
    app/lib/test_module.rb:24:in `method_missing' 
    app/lib/test_module.rb:24:in `method_missing' 
    app/lib/test_module.rb:24:in `method_missing' 
    ... 

缺少的方法是'id'?!?您會注意到,我已經註釋到了將缺少的方法發送到相關類的示例代碼行 - text_page.send(method,* args,& block) - 因爲只是調用關聯 - text_page - 就足夠了觸發堆棧級別太深的錯誤。

任何人都可以發現錯誤?

PS。當然,這是實際模塊和用例的一個簡化例子,但是這說明了錯誤,並且失敗了。


SOLUTION

大感謝亞歷克斯的保存。 ActiveRecord Id是使用方法缺失塊動態生成的。下面的代碼工作,因爲它讓:身份證丟失的方法向下傳遞到超:

def method_missing(method, *args, &block) 
    if method != :id && text_page.respond_to?(method) 
     text_page.send(method, *args, &block) 
    else 
     super 
    end 
end 

回答

2

埃裏克 - 如果我沒有記錯,AR使用method_missing方法來定義屬性訪問器和類等,例如它們不是硬編碼的。它們存儲在實例變量中,但.id和.id =方法是即時定義的。因此,我建議定義一種方法來匹配想要引用相關接口的缺少方法。

+0

你可能使用 如果text_page.methods.include?(方法) text_page.send(方法,*指定參數時,與塊) 其他 超(方法,*指定參數時,與塊) 結束 – Alex 2011-01-20 04:17:05