【问题标题】:Where is the best place to add methods to the Integer class in Rails?在 Rails 中向 Integer 类添加方法的最佳位置在哪里?
【发布时间】:2008-11-05 21:42:41
【问题描述】:

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

【问题讨论】:

    标签: ruby-on-rails ruby monkeypatching


    【解决方案1】:

    如果您一心想使用数字(或整数等)类来进行单位转换,那么至少要在逻辑上进行并具有一些实际价值。

    首先,创建一个 Unit 类来存储单位类型(米、英尺、肘等)和创建时的值。然后向 Numeric 添加一堆方法,这些方法对应于 unit 可以具有的有效值:这些方法将返回一个 Unit 对象,其类型记录为方法名称。 Unit 类将支持一堆 to_* 方法,这些方法将转换为具有相应单位值的另一种单位类型。这样,您可以执行以下命令:

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

    处理它的最佳方法可能是 Unit 类中的转换类型和表达式矩阵,然后使用 method_missing 来检查给定类型是否可以转换为另一种类型。在数值类中,使用 method_missing 询问 Unit 是否支持给定方法作为单位类型,如果支持,则返回使用数值作为其值的请求类型的单位对象。然后,您可以通过向 Unit 添加一个扩展转换矩阵的 register_type 和 register_conversion 类方法来支持在运行时添加单位和转换,并且 Numeric 将“自动”获得该功能。

    至于放在哪里,创建一个 lib/units.rb 文件,该文件还包含 Numeric 的 monkey_patch,然后在需要 lib/units.rb 文件的 config/environment.rb 中初始化它。

    【讨论】:

    • 我建议做的唯一不同的事情是使用初始化程序目录而不是在 environment.rb 中进行初始化。很棒的帖子。
    【解决方案2】:

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

    如“requre 'unitCoversions'”

    如果你足够努力的话,很有可能已经有人这样做了:)

    但是不要尝试修改原生核心类,那只会以 Misery 结束。

    (此外,您要扩展的类是 'numeric' ,它将适用于整数和浮点数:))

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

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

    在没有好的选择时这样做。

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

    例如,翻转数据库。

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

    等等等等,有多少不好的方法可以做到这一点是没有限制的。

    "Bob".createUser(); 
    

    杯中的苦难。

    如果你想做一些实际的事情,有一个转换类或函数,

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

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

    【讨论】:

    • 不完全清楚为什么我不应该这样做......Rails 对字符串类这样做取得了巨大的成功。
    【解决方案3】:

    为什么不只是:

    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】:

      我同意猴子补丁应该谨慎使用,但有时它只是有意义的。我真的很喜欢允许您输入 5.days.ago 的助手,它们是 active_support 库的一部分

      因此,在这种情况下,其他一些答案可能会更好,但如果您要扩展 ruby​​ 类,我们会将所有扩展保留在 lib/extensions/class_name.rb 中

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

      【讨论】:

        【解决方案5】:

        通常(和逻辑上)整数不能转换为英里或米。听起来您可能想要创建一个新类,如“英尺”或“英寸”,它用整数初始化,然后包含 size_in_miles 或 size_in_meters 等方法。为方便起见,这些方法可以返回十进制或浮点类型,但您可能还想编写英里类或米类。

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

        Float feetToMiles(integer I)

        你会打电话给

        miles = Feet.feetToMiles(5280);

        并获取miles = 1.0

        【讨论】:

          【解决方案6】:

          意识到这个问题很老,但我认为最清晰的方法是创建一个具有两个属性 @length@unit 的距离类。

          您只需要一个转换哈希,可能作为距离的类变量:

          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
          

          【讨论】:

            【解决方案7】:

            如果您打算这样做,但您不应该这样做,那么您可以将代码放入:

            config/initializers/add_methods_that_are_naughty_to_numeric.rb
            

            Rails 会自动为您运行这些。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2022-01-12
              • 1970-01-01
              • 1970-01-01
              • 2021-12-11
              • 2011-07-02
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多