2008-11-05 59 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 
相关问题