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