Frage

Wo ist der beste Ort, um eine Methode, um die Integer-Klasse in Rails hinzufügen? Ich möchte eine to_meters und to_miles Methoden hinzuzufügen.

War es hilfreich?

Lösung

Wenn Sie Ihr Herz auf Ausmisten mit dem Numeric (oder integer, etc) gesetzt haben Klasse Einheit Umwandlung zu bekommen, dann zumindest tut es logisch und mit einigem echten Wert.

Sie zunächst eine Anteilsklasse erstellen, die den Einheitentyp (Meter, Fuß, Ellen, etc.) und den Wert bei der Erstellung speichert. Dann fügen Sie eine Reihe von Methoden, um Numeric, die auf die gültigen Werte Einheit entsprechen haben: diese Methoden eine Einheit Objekt zurück mit seiner Art als Methodennamen aufgezeichnet. Die Anteilklasse würde ein Bündel to_ * Methoden unterstützen, die zu einer anderen Einheit der Art mit dem entsprechenden Einheitswert umwandeln würden. Auf diese Weise können Sie den folgenden Befehl tun:

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

Der besten Weg, es zu handhaben wahrscheinlich eine Matrix von Conversion-Typ und Ausdrücke in der Anteilklasse sein würde, dann method_missing verwenden zu überprüfen, ob ein bestimmte Typ in einem anderen Typ umgewandelt werden kann. Bei der numerischen Klasse verwenden method_missing Einheit zu fragen, ob es die angegebene Methode als Einheit Typen unterstützt, und wenn ja, eine Einheit Objekt des angeforderten Typs zurückgeben die numerischen als Wert verwendet wird. Sie könnten dann Geräte und Umbauten zur Laufzeit durch das Hinzufügen einer register_type und register_conversion Klassenmethode Einheit, die die Konversionsmatrix und Numeric verlängert würde „automatisch“ holt die Fähigkeit unterstützen, hinzugefügt wird.

Was, wo es setzen, erstellen Sie eine lib / units.rb Datei, die auch die monkey_patch zu Numeric enthalten würde, initialisieren Sie es dann in config / environment.rb bu erfordert die lib / units.rb Datei.

Andere Tipps

Erstellen Sie Ihr eigenes Modul / Bibliothek, die Sie in den Gültigkeitsbereich enthalten, wenn Sie es brauchen um diese Aufgabe auszuführen.

Wie "requre 'unitCoversions'"

Und die Chancen sind, jemand hat dies bereits getan, wenn man hart genug:)

Allerdings DONT versuchen, die nativen Kern Klasse ändern, die nur in Misery enden wird.

(Auch die Klasse, die Sie erweitern möchten, ist ‚numerisch‘, die beide auf ganzer Zahlen und Floats gelten :))

  

Nicht ganz klar, warum ich soll dies ... Rails nicht tut dies auf die String-Klasse mit großem Erfolg.

Weil es können erfolgen bedeutet es nicht, sollte erfolgen. ‚Monkey Patching‘, wie es bekannt ist, kann alle Arten von ungeraden Nebenwirkungen hat, und sie können ein episches Versagen sein, wenn falsch gemacht.

Do it, wenn es keine gute Alternative.

Denn wenn man wirklich etwas tun Daft wollte, könnte man einen ganzen Rahmen bauen, dass ALL es tat, war Affe die Kern-Klassen patchen.

Just zum Beispiel Flip databasing auf dem Kopf.

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

etc etc. gibt es keine Grenze, wie viele schlechte Möglichkeiten es gibt, das zu tun.

"Bob".createUser(); 

Elend in einer Tasse.

Wenn Sie praktisch etwas tun wollen, haben eine Convert-Klasse oder Funktion,

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

zumindest Sie verschmutzen nicht die globalen Namensraum und Kernfunktionen, die Art und Weise, und es macht mehr Sinn kohärent.

Warum nicht einfach:

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

Nutzung:

Feet.in_miles 2313

Vielleicht schauen Sie es in die andere Richtung:

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

Miles.from_feet 2313

Ich bin damit einverstanden Affe Patchen mit Vorsicht verwendet werden soll, aber gelegentlich nur Sinn machen. Ich mag die Helfer, die Ihnen erlauben 5.days.ago zu geben, die Teil der active_support Bibliothek sind

So einige der anderen Antworten könnten in diesem Fall besser sein, aber wenn man Ruby-Klassen erweitern wir halten alle unsere Erweiterungen in lib / extensions / class_name.rb

auf diese Weise, wenn an einem Projekt arbeitet schnell und einfach ist, etwas zu finden und zu sehen, die mit Standardklassen aus dem Üblichen sein könnten.

Normalerweise (und logisch), ganze Zahlen nicht in Meilen oder in Metern umgerechnet werden. Es klingt wie Sie eine neue Klasse wie „Feet“ oder „Zoll“ erstellen möchten, die mit einer ganzen Zahl initialisiert wird, dann enthält Methoden wie size_in_miles oder size_in_meters. Zur Vereinfachung könnten diese Methoden geben dezimal oder Typen schwimmen, aber Sie mögen vielleicht auch eine Meilen-Klasse oder einen Meter Klasse schreiben.

Als eine alternative Methode, möchten Sie vielleicht eine statische Methode in der neuen Klasse erstellen, die eine Signatur wie diese haben würde:

Float feetToMiles(integer I)

, die Sie nennen würde

miles = Feet.feetToMiles(5280);

und erhalten miles = 1.0

Erkennen die Frage ist alt, aber ich denke, der klarste Weg, um eine Entfernung Klasse mit zwei Attributen @length und @unit zu machen wäre.

Sie würden nur eine Conversion Hash benötigen, wahrscheinlich als Klassenvariable der Entfernung:

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

Und es aussehen würde, ein bisschen wie:

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

, die ich ehrlich denkt, sieht besser aus als

3.meters.to_feet

Wenn Sie wollen, dies tun, die Sie sollen nicht, dann würden Sie Ihren Code setzen in:

config/initializers/add_methods_that_are_naughty_to_numeric.rb

Schienen würden diese für Sie automatisch ausgeführt werden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top