2008-11-05 52 views

回答

11

如果你已經開始用Numeric(或整數等)類進行單元轉換,那麼至少應該在邏輯上和一些實際值上做。

首先,創建一個Unit類,存儲單位類型(米,英尺,肘等等)和創建時的值。然後在Numeric中添加一些與有效值單元可以對應的方法:這些方法將返回一個Unit對象,並將其類型記錄爲方法名稱。 Unit類將支持一堆to_ *方法,這些方法將轉換爲具有相應單位值的另一個單位類型。這樣一來,您可以執行以下命令:

>> x = 47.feet.to_meters 
=> 14.3256 
>> x.inspect 
=> #<Unit 0xb795efb8 @value=14.3256, @type=:meter> 

來處理它很可能是轉換類型和表達式的單位類的矩陣,然後使用method_missing方法來檢查,如果給定的類型可以轉換的最佳方式到另一種類型。在數字類中,使用method_missing詢問Unit是否支持給定方法作爲單位類型,如果是,則返回一個使用數字作爲其值的請求類型的單位對象。然後,您可以在運行時支持添加單位和轉換,方法是在Unit中添加register_type和register_conversion類方法,以擴展轉換矩陣,並且Numeric將「自動」提取能力。

至於在哪裏放置它,創建一個lib/units.rb文件,它也包含monkey_patch到Numeric,然後在需要lib/units.rb文件的config/environment.rb bu中初始化它。

+1

我建議做的唯一不同的是使用initializers目錄而不是在environment.rb中進行初始化。好帖子。 – jonnii 2008-11-07 20:26:02

2

通常(和邏輯上),整數不能轉換爲英里或米。這聽起來像你可能想創建一個新的類,如「英尺」或「英寸」,用一個整數初始化,然後包含像size_in_miles或size_in_meters等方法。爲了方便起見,這些方法可能會返回小數或浮點類型,但您可能還想寫一個英里類或米類。

作爲一種替代方法,您可能希望創建新類的靜態方法,將有這樣的簽名:

Float feetToMiles(integer I)

,你會打電話

miles = Feet.feetToMiles(5280);

並獲得miles = 1.0

2

創建您自己的模塊/庫whi當你需要它來執行這個任務時,你可以將其納入範圍。

如「requre‘unitCoversions’」

機會是,有人已經做到了這一點,如果你看夠硬:)

然而DONT嘗試修改原生性核心類,只會在苦難中結束。

(另外,要擴展的類是「數字」,這將同時適用於整數和浮點數:))

尚不完全清楚,爲什麼我不應該這樣做... Rails會這對字符串類來說是非常成功的。

因爲它可以做並不意味着它應該來完成。衆所周知,「猴子補丁」可能會產生各種各樣的奇怪副作用,並且在做錯了時可能會成爲史詩般的失敗。

當沒有好的選擇時就做。

因爲如果你真的想做一些愚蠢的事情,你可以建立一個完整的框架,ALL它做的是猴子補丁的核心類。

只是例如,在它的頭上翻轉數據庫。

5.getArtist(); 
10.getEvent(); 
100.getTrack(); 

等等,這樣做有多少壞方法沒有限制。

"Bob".createUser(); 

一杯苦難。

如果你想要做一些實事,有一個轉換類或函數,

convert(3 , { :from=>:miles, :to=>:meters }); 

至少你不會污染全局命名空間和核心職能的這種方式,這讓更多的層次感。

+0

不完全清楚爲什麼我不應該這樣做...... Rails會將此操作傳遞給字符串類以取得巨大成功。 – Ben 2008-11-05 22:05:49

-1

如果你要做到這一點,你應該沒有,那麼你會把你的代碼:

config/initializers/add_methods_that_are_naughty_to_numeric.rb 

的Rails將自動爲您運行這些。

2

爲什麼不乾脆:

class Feet 
    def self.in_miles(feet) 
    feet/5280 
    end 
end 

用法:

Feet.in_miles 2313 

或者,也許看看它的其他方式:

class Miles 
    def self.from_feet(feet) 
    feet/5280 
    end 
end 

Miles.from_feet 2313 
2

我同意猴子打補丁應小心使用,但偶爾它纔有意義。我真的很喜歡助手,可以鍵入5.days.ago這是active_support庫的一部分

所以在這種情況下,其他一些答案可能會更好,但如果您要擴展ruby類,我們將保留所有lib/extensions/class_name.rb中的擴展

這種方式在項目上工作時,可以快速輕鬆地找到並查看任何可能與標準類不同的事情。

0

認識到這個問題很古老,但我認爲最清晰的方法是製作一個具有兩個屬性的距離類@length和​​。

你只需要一個轉換的哈希,可能是因爲距離的類變量:

class Distance 

    @@conversion_rates = { 
    meters: { 
     feet: 3.28084, 
     meters: 1.0 
    } 
    } 

    def to(new_unit) 
    new_length = @length * @@conversion_rates[@unit][new_unit] 
    Distance.new(new_length, new_unit) 
    end 

end 

而且它看起來有點像:

Distance.new(3, :meters).to(:feet) 

其中老實說,我認爲看起來比

更好
3.meters.to_feet 
相關問題