在Rails中向整数类添加方法的最佳位置在哪里? 我想添加 to_meters to_miles 方法。

有帮助吗?

解决方案

如果你的心脏被设置为使用数字(或整数等)类进行单位转换,那么至少要逻辑地并且具有一些实际价值。

首先,创建一个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文件。

其他提示

创建您自己的模块/库,在需要它执行此任务时将其包含在范围内。

例如“requre”unitCoversions'&quot;

而且很有可能,如果你看起来很努力,有人已经这样做了。)

然而 DONT 尝试修改本机核心类,这只会以Misery结束。

(另外,你要扩展的类是'numeric',它将适用于Integers和Floats :))

  

不完全清楚为什么我不应该这样做... Rails对字符串类做了很大的成功。

因为可以完成并不意味着应该完成。众所周知,“猴子修补”会产生各种奇怪的副作用,如果做错了,它们可能是史诗般的失败。

当没有好的替代方案时这样做。

因为如果你真的想做一些愚蠢的事情,你可以构建一个完整的框架 ALL 它所做的就是猴子修补核心类。

例如,在其头部翻转数据库。

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

等等,对于有多少糟糕的方法没有限制。

"Bob".createUser(); 
一杯苦难。

如果你想做一些实际的事情,请使用转换类或函数,

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

至少你没有以这种方式污染全局命名空间和核心功能,而且它具有更强的连贯性。

为什么不呢:

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

这样,在处理项目时,可以快速轻松地找到并查看标准类可能与众不同的任何内容。

通常(和逻辑上),整数不能转换为里程或米。听起来你可能想创建一个像“脚”这样的新类。或“英寸”或“英寸”用整数初始化,然后包含size_in_miles或size_in_meters等方法。为方便起见,这些方法可以返回decimal或float类型,但您可能还想写一个里程类或米类。

作为替代方法,您可能希望在新类中创建一个具有如下签名的静态方法:

Float feetToMiles(整数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会自动为你运行这些。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top