Pregunta

¿Dónde está el mejor lugar para agregar un método a la clase entera en Rails? Me gustaría agregar un to_meters y to_miles métodos.

¿Fue útil?

Solución

Si tiene el corazón puesto en mucking con la clase Numeric (o entero, etc.) para obtener la conversión de unidades, entonces al menos hágalo lógicamente y con algún valor real.

Primero, cree una clase de Unidad que almacene el tipo de unidad (metros, pies, codos, etc.) y el valor en la creación. Luego, agregue un grupo de métodos a Numeric que correspondan a los valores válidos que puede tener la unidad: estos métodos devolverán un objeto Unit con su tipo registrado como el nombre del método. La clase Unidad admitiría un montón de métodos to_ * que convertirían a otro tipo de unidad con el valor de unidad correspondiente. De esa manera, puede hacer el siguiente comando:

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

La mejor manera de manejarlo probablemente sería una matriz de tipos y expresiones de conversión en la clase Unidad, luego use method_missing para verificar si un tipo dado puede convertirse a otro tipo. En la clase numérica, use method_missing para preguntarle a Unit si es compatible con el método dado como un tipo de unidad, y si es así, devuelva un objeto de unidad del tipo solicitado utilizando el numérico como su valor. A continuación, podría admitir la adición de unidades y conversiones en tiempo de ejecución al agregar un método de clase register_type y register_conversion a Unit que extendiera la matriz de conversión y Numeric 'automágicamente'. recoger la habilidad.

En cuanto a dónde colocarlo, cree un archivo lib / units.rb, que también contendría el monkey_patch a Numeric, luego inicialícelo en config / environment.rb bu que requiera el archivo lib / units.rb.

Otros consejos

Cree su propio módulo / biblioteca que incluya en el alcance cuando lo necesite para realizar esta tarea.

Tal como " requre 'unitCoversions' "

Y lo más probable es que alguien ya haya hecho esto si te fijas lo suficiente :)

Sin embargo, NO intente modificar la clase principal nativa, que solo terminará en Miseria.

(Además, la clase que desea ampliar es 'numérica', que se aplicará tanto a los enteros como a los flotantes :))

  

No está del todo claro por qué no debería hacer esto ... Rails hace esto a la clase de cadena con gran éxito.

Porque puede hacerse no significa que debería hacerse. El "parche de mono", como se le conoce, puede tener todo tipo de efectos secundarios extraños, y puede ser un fracaso épico cuando se hace mal.

Hazlo cuando no haya una buena alternativa.

Porque si realmente quisieras hacer algo tonto, podrías construir un marco completo que ALL hiciera fue parchear mono en las clases principales.

Solo por ejemplo, voltee la base de datos sobre su cabeza.

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

etc. etc. no hay límite para la cantidad de malas maneras de hacerlo.

"Bob".createUser(); 

miseria en una taza.

Si desea hacer algo práctico, tenga una clase o función Convertir,

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

al menos no estás contaminando el espacio de nombres global y las funciones centrales de esa manera y tiene un sentido más coherente.

Por qué no solo:

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

uso:

Feet.in_miles 2313

O tal vez míralo de otra manera:

class Miles
  def self.from_feet(feet)
    feet/5280
  end
end

Miles.from_feet 2313

Estoy de acuerdo en que los parches de mono deben usarse con cuidado, pero ocasionalmente solo tiene sentido. Realmente me gustan los ayudantes que le permiten escribir 5.days.ago que son parte de la biblioteca active_support

Entonces, algunas de las otras respuestas podrían ser mejores en este caso, pero si está extendiendo las clases de ruby, mantenemos todas nuestras extensiones en lib / extensions / class_name.rb

de esta manera, cuando se trabaja en un proyecto, es rápido y fácil encontrar y ver cualquier cosa que pueda estar fuera de lo común con las clases estándar.

Normalmente (y lógicamente), los enteros no se pueden convertir a millas o metros. Parece que es posible que desee crear una nueva clase como "Pies" o "pulgadas" que se inicializa con un número entero, luego contiene métodos como size_in_miles o size_in_meters. Por conveniencia, esos métodos podrían devolver tipos decimales o flotantes, pero es posible que también desee escribir una clase de millas o una clase de metros.

Como método alternativo, es posible que desee crear un método estático en su nueva clase que tenga una firma como esta:

Float feetToMiles (entero I)

que llamarías

miles = Feet.feetToMiles (5280);

y obtenga miles = 1.0

Date cuenta de que la pregunta es antigua, pero creo que la forma más clara sería hacer una clase de Distancia con dos atributos @length y @unit .

Solo necesitaría un hash de conversión, probablemente como una variable de clase de Distancia:

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

Y se vería como:

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

que honestamente creo que se ve mejor que

3.meters.to_feet

Si fuera a hacer esto, lo cual no debería hacer, entonces pondría su código en:

config/initializers/add_methods_that_are_naughty_to_numeric.rb

Rails los ejecutaría automáticamente por usted.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top