Wo ist der beste Ort, um Methoden, um die Integer-Klasse in Rails hinzufügen?
-
06-07-2019 - |
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.
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.