2011-07-29 19 views
3

我想在模塊中放置一些代碼,如果某些方法未定義,則會引發錯誤。 該模塊依賴於此方法的外部定義,因爲此方法的實現對於所有類都是不同的。該代碼可以幫助開發人員儘早知道他們忘記實施該方法,而不是在他們嘗試使用該模塊的功能時。Ruby:如果沒有找到類方法,則在Module中引發錯誤

module MyModule 
    def self.included(klass) 
    raise "MyModule: please `def my_method` on #{klass}" unless klass.respond_to?(:my_method) 
    end 
end 

我可以很容易地在一個模塊包括定義產生一個錯誤,如果沒有定義的方法,但是由於大多數模塊都包含在文件的頂部,很可能是我要求的方法是在類中定義,但不包括我的模塊之前。

class MyClass 
    include MyModule 
    def self.my_method 
    # ... 
    end 
end 

這仍然引發錯誤:(

是否有可能只提出如果該方法確實在類定義中沒有定義?幾乎需要各種各樣的class.onload回調錯誤。如果沒有任何其他的想法,如何緩解的可能性,程序員可能包括我們的模塊沒有確定這個需要的方法?

回答

5

聽起來像是你想使用的method_missingdefine_method

如果您請使用method_missing別忘了:

的樣子。

更新:

這聽起來我們的目標是做靜態方法檢查如Java或C++一樣。這不是紅寶石:-(

真正有意義由於紅寶石:

  • 對象的每個實例都有自己的eigenclass一個給定的對象可能有在運行時混在必要的方法,所以只是因爲。 Foo沒有在類裝入時間的方法是沒有意義的。
  • 框架等RoR的鉤method_missing的和動態地創建所需的數據庫查詢方法的方法,因此該方法可能存在(或不)在需要時。

關於「加載類」:類定義確實執行。試試這個:

class Foo 
    p "Hi" 
end 

你會看到「嗨」第一,僅在第一次使用美孚。這是怎麼樣的事情像devise勾成他們的魔力。

class User < ActiveRecord::Base 
    # **CALL 'devise' method** 
    devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable 

    # **CALL attr_accessible method** 
    attr_accessible :email, :password, :password_confirmation 
end 

因此,也許私人約定有開發商加入check_class方法調用到相關類的底部?

我理解這個意圖,但它似乎是與ruby設計工作的方式作鬥爭。

作爲一個主要的Java人,我很欣賞挫敗感。讓我猜猜:重複發生的代碼被推向生產過程中缺少方法的情況? :-P

UPDATE2:

WRT onload在紅寶石禁止使用冷凍一類的獲得新的方法來定義所有的時間。 (或者一個實例可以爲那個實例定義新的方法),所以檢查一個方法的不存在只是一個快照檢查,並不像靜態語言帶來的檢查那樣明確。這是紅寶石自己的Halting problem

+1

我熟悉特徵類,是的,我試圖做類似靜態方法檢查。我的一位同事指出,我們可以將這種期望轉化爲對實現MyModule的模型的測試。我們可以有一個宏acts_as_my_module,我們可以將其與所有模型測試/規格混合使用。仍然不會大聲抱怨,並需要額外的程序員的奉獻精神,但是是最紅寶石般的 – Schneems

+0

如果你使用rspec,你可以做這樣的事情http://relishapp.com/rspec/rspec-core/v/ 2-6/dir/example-groups /共享示例 – Schneems

+0

考慮到所有事情,您可能確實需要一個作爲部署運行的工具,並在出現類似問題時停止部署。這聽起來像你知道已經但希望有替代:-) – Pat

3

如何聲明具有該名稱的方法,這只是引發錯誤,以確保用戶重新定義方法?

module MyModule 
    def my_method 
    raise "Please implement me" 
    end 
end 


class MyClass 
    include MyModule 
    def my_method 
    # do something 
    end 
end 
+0

我考慮過這個,儘管在嘗試調用這個方法之前你仍然感覺不到這種痛苦。 – Schneems

+0

如果你完全忽略了這個定義,它幾乎會有相同的效果。事實上,它會更好*,因爲它不會引發通用的非描述性RunTimeError異常,而是會引發一個'NoMethodError'異常,它告訴你幾乎所有你需要知道的:一個預期的方法在那裏,沒有。這就是Ruby的慣用方式,例如'Enumerable'和'Comparable'就是這樣做的。 –

2

假設你的程序需要的所有文件開始的時候並沒有使用任何autoload之類的,你可以使用類似下面的一切都需要經過正確的,但該計劃真正開始之前:

classes_to_check = Object.constants.find_all do |const| 
    klass = Object.const_get(c) 
    klass.ancestors.include?(MyModule) if klass.kind_of?(Module) 
end 

classes_to_check.each do |klass| 
    raise "MyModule: please `def my_method` on #{klass}" \ 
    unless klass.respond_to?(:my_method) 
end 

但是,我個人總是使用Dogbert的解決方案。

相關問題