在Rails中向整数类添加方法的最佳位置在哪里?
我想添加to_meters
和to_miles
方法。
答案 0 :(得分:11)
如果你的心脏被设置为使用数字(或整数等)类进行单位转换,那么至少要逻辑地并且具有一些实际价值。
首先,创建一个Unit类,用于存储单位类型(米,英尺,立方等)和创建时的值。然后向Numeric添加一组与单元可以具有的有效值对应的方法:这些方法将返回一个Unit对象,其类型记录为方法名称。 Unit类将支持一堆to_ *方法,这些方法将转换为具有相应单位值的另一个单元类型。这样,您可以执行以下命令:
>> x = 47.feet.to_meters
=> 14.3256
>> x.inspect
=> #<Unit 0xb795efb8 @value=14.3256, @type=:meter>
处理它的最佳方法可能是Unit类中的转换类型和表达式矩阵,然后使用method_missing检查给定类型是否可以转换为另一种类型。在numeric类中,使用method_missing询问Unit是否支持给定方法作为单元类型,如果是,则使用numeric作为其值返回所请求类型的单元对象。然后,您可以通过向Unit添加register_type和register_conversion类方法来支持在运行时添加单位和转换,扩展转换矩阵,Numeric将“自动”获取该功能。
至于放置它的位置,创建一个lib / units.rb文件,该文件还包含Monkey_patch到Numeric,然后在config / environment.rb中初始化它,需要lib / units.rb文件。
答案 1 :(得分:2)
通常(和逻辑上),整数不能转换为里程或米。听起来你可能想要创建一个新的类,如“Feet”或“inches”,用一个整数初始化,然后包含size_in_miles或size_in_meters等方法。为方便起见,这些方法可以返回decimal或float类型,但您可能还想写一个里程类或米类。
作为替代方法,您可能希望在新类中创建一个具有如下签名的静态方法:
Float feetToMiles(integer I)
miles = Feet.feetToMiles(5280);
并获取miles = 1.0
答案 2 :(得分:2)
创建您自己的模块/库,在需要它执行此任务时将其包含在范围内。
例如“requre'unitCoversions'”
而且很有可能,如果你看起来很努力,有人已经这样做了。)
然而 DONT 尝试修改本机核心类,这只会以Misery结束。
(另外,你要扩展的类是'numeric',它将适用于Integers和Floats :))
不完全清楚为什么我不应该这样做... Rails对字符串类做了很大的成功。
因为可以完成并不意味着应该完成。众所周知,“猴子修补”会产生各种奇怪的副作用,如果做错了,它们可能是史诗般的失败。
当没有好的替代方案时这样做。
因为如果你真的想做一些愚蠢的事情,你可以建立一个完整的框架 ALL 它所做的就是猴子修补核心类。
例如,在其头部翻转数据库。
5.getArtist();
10.getEvent();
100.getTrack();
等等,对于有多少糟糕的方法没有限制。
"Bob".createUser();
一杯苦难。
如果你想做一些实际的事情,请使用转换类或函数,
convert( 3 , { :from=>:miles, :to=>:meters });
至少你没有以这种方式污染全局命名空间和核心功能,而且它具有更强的连贯性。
答案 3 :(得分: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
答案 4 :(得分:2)
我同意猴子补丁应该小心使用,但偶尔它才有意义。我非常喜欢帮助你输入5.days.ago的助手,它们是active_support库的一部分
因此,在这种情况下,其他一些答案可能会更好,但如果您要扩展ruby类,我们将所有扩展保留在lib / extensions / class_name.rb
这样,在处理项目时,可以快速轻松地找到并查看标准类可能与众不同的任何内容。
答案 5 :(得分:0)
意识到问题已经过时了,但我认为最明确的方法是制作一个具有两个属性@length
和@unit
的距离类。
您只需要一个转换哈希,可能是Distance的一个类变量:
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
答案 6 :(得分:-1)
如果您打算这样做,那么您不应该这样做,那么您可以将代码放入:
config/initializers/add_methods_that_are_naughty_to_numeric.rb
Rails会自动为你运行这些。