代码之家  ›  专栏  ›  技术社区  ›  Ben Crouse

在Rails中,向integer类添加方法的最佳位置是哪里?

  •  5
  • Ben Crouse  · 技术社区  · 16 年前

    在Rails中,向integer类添加方法的最佳位置是哪里? 我想加一个 to_meters to_miles 方法。

    7 回复  |  直到 8 年前
        1
  •  11
  •   dennisjbell    16 年前

    如果您的心已经准备好与numeric(或integer,等等)类进行mucking以获得单位转换,那么至少要在逻辑上使用一些实际值进行转换。

    首先,创建一个单元类,它存储单元类型(米、英尺、立方等)和创建时的值。然后将一组方法添加到与Unit可以拥有的有效值相对应的数值中:这些方法将返回一个Unit对象,其类型记录为方法名。Unit类将支持一组to_*方法,这些方法将转换为具有相应单位值的另一种单位类型。这样,您可以执行以下命令:

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

    处理它的最佳方法可能是单元类中转换类型和表达式的矩阵,然后使用缺少的方法检查给定类型是否可以转换为其他类型。在Numeric类中,使用方法“Missing”询问Unit是否支持将给定方法作为Unit类型,如果支持,则返回请求类型的Unit对象,并使用数字作为其值。然后,您可以在运行时支持添加单位和转换,方法是将register_type和register_conversion类方法添加到扩展转换矩阵的单位,numeric将“自动”获得这种能力。

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

        2
  •  2
  •   Kent Fredric    16 年前

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

    例如“Require‘UnitCoverations’”

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

    然而 尝试修改本机核心类,这只会导致痛苦。

    (另外,要扩展的类是“numeric”,它将同时应用于整数和浮点数:)

    不完全清楚为什么我不应该这样做…Rails对String类执行此操作,从而获得巨大成功。

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

    当没有好的选择时就去做。

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

    例如,根据数据头部翻转数据。

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

    等等。有多少不好的方法是没有限制的。

    "Bob".createUser(); 
    

    杯中的痛苦。

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

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

    至少您不会以这种方式污染全局名称空间和核心函数,而且它更有条理。

        3
  •  2
  •   Cameron Booth    16 年前

    为什么不只是:

    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
  •   danmayer    16 年前

    我同意猴子修补应该小心使用,但有时它只是有意义的。我真的很喜欢那些允许你在5天前输入的助手,它们是活动的支持库的一部分。

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

    通过这种方式,在处理一个项目时,可以快速、轻松地发现和查看标准类中可能不寻常的内容。

        5
  •  2
  •   mr rogers    8 年前

    通常(逻辑上),整数不能转换为英里或米。听起来您可能想要创建一个新的类,比如用整数初始化的“feet”或“inches”,然后包含类似于size_in_miles或size_in_meters的方法。为了方便起见,这些方法可以返回decimal或float类型,但您也可能希望编写miles类或meters类。

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

    Float feetToMiles(integer I)

    你会打电话给

    miles = Feet.feetToMiles(5280);

    得到 miles = 1.0

        6
  •  0
  •   AJcodez    11 年前

    意识到这个问题已经过时了,但我认为最清楚的方法是建立一个具有两个属性的距离类 @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
  •  -1
  •   jonnii    16 年前

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

    config/initializers/add_methods_that_are_naughty_to_numeric.rb
    

    Rails会自动为您运行这些。