Where is the best place to add methods to the Integer class in Rails?

前端 未结 7 2202
死守一世寂寞
死守一世寂寞 2021-02-10 05:56

Where is the best place to add a method to the integer class in Rails? I\'d like to add a to_meters and to_miles methods.

相关标签:
7条回答
  • 2021-02-10 06:31

    If you were going to do this, which you shouldn't, then you would put your code into:

    config/initializers/add_methods_that_are_naughty_to_numeric.rb
    

    Rails would automatically run these for you.

    0 讨论(0)
  • 2021-02-10 06:42

    Realize the question is old, but I think the clearest way would be to make a Distance class with two attributes @length and @unit.

    You'd just need a conversion hash, probably as a class variable of 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
    

    And it would look kinda like:

    Distance.new(3, :meters).to(:feet)
    

    which i honestly think looks better than

    3.meters.to_feet
    
    0 讨论(0)
  • 2021-02-10 06:43

    If you have your heart set on mucking with the Numeric (or integer, etc) class to get unit conversion, then at least do it logically and with some real value.

    First, create a Unit class that stores the unit type (meters,feet, cubits, etc.) and the value on creation. Then add a bunch of methods to Numeric that correspond to the valid values unit can have: these methods will return a Unit object with it's type recorded as the method name. The Unit class would support a bunch of to_* methods that would convert to another unit type with the corresponding unit value. That way, you can do the following command:

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

    The best way to handle it would probably be a matrix of conversion types and expressions in the Unit class, then use method_missing to check if a given type can be converted to another type. In the numeric class, use method_missing to ask Unit if it supports the given method as a unit type, and if so, return a unit object of the requested type using the numeric as its value. You could then support adding units and conversions at runtime by adding a register_type and register_conversion class method to Unit that extended the conversion matrix and Numeric would "automagically" pick up the ability.

    As for where to put it, create a lib/units.rb file, which would also contain the monkey_patch to Numeric, then initialize it in config/environment.rb bu requiring the lib/units.rb file.

    0 讨论(0)
  • 2021-02-10 06:49

    Normally (and logically), integers can't be converted to miles or to meters. It sounds like you may want to create a new class like "Feet" or "inches" that is initialized with an integer, then contains methods like size_in_miles or size_in_meters. For convenience those methods could return decimal or float types, but you might also want to write a miles class or a meters class.

    As an alternate method, you might want to create a static method in your new class that would have a signature like this:

    Float feetToMiles(integer I)

    that you would call

    miles = Feet.feetToMiles(5280);

    and get miles = 1.0

    0 讨论(0)
  • 2021-02-10 06:53

    Why not just:

    class Feet
      def self.in_miles(feet)
        feet/5280
      end
    end
    

    usage:

    Feet.in_miles 2313
    

    Or maybe look at it the other way:

    class Miles
      def self.from_feet(feet)
        feet/5280
      end
    end
    
    Miles.from_feet 2313
    
    0 讨论(0)
  • 2021-02-10 06:54

    Create your own module/library which you include into scope when you need it to perform this task.

    Such as "requre 'unitCoversions' "

    And Chances are, somebody has already done this if you look hard enough :)

    However DONT try modifying the native core class, that will only end in Misery.

    ( Also, the class you want to extend is 'numeric' , that will apply to both Integers and Floats :) )

    Not entirely clear why I shouldn't do this... Rails does this to the string class to great success.

    Because it can be done doesn't mean it should be done. 'Monkey Patching' as it is known can have all sorts of odd side effects, and they can be an epic failure when done wrong.

    Do it when there is no good alternative.

    Because if you really wanted to do something daft, you could build an entire framework that ALL it did was monkey patch the core classes.

    Just for example, flip databasing on its head.

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

    etc etc. there is no limit to how many bad ways there are to do that.

    "Bob".createUser(); 
    

    misery in a cup.

    If you want to do something practical, have a Convert class or function,

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

    at least you're not polluting the global namespace and core functions that way and it makes more coherent sense.

    0 讨论(0)
提交回复
热议问题