6 Stimmen

globale methoden in ruby on rails modelle

Ich habe in allen meinen Modellen Methoden, die wie folgt aussehen:

def formatted_start_date
  start_date ? start_date.to_s(:date) : nil
end

Ich möchte etwas haben, das automatisch eine Methode wie diese für jedes datetime-Feld in jedem Modell schreibt, was ist der beste Weg, dies zu tun?

-C

17voto

Brian Hogan Punkte 3013

Ich musste diese Frage einfach beantworten, weil es eine lustige Ruby-Übung ist.

Das Hinzufügen von Methoden zu einer Klasse kann auf viele Arten erfolgen, aber eine der besten Möglichkeiten ist die Verwendung einiger der Reflexions- und Evaluierungsfunktionen von Ruby.

Erstellen Sie diese Datei in Ihrem lib-Ordner als lib/date_methods.rb

module DateMethods

  def self.included(klass)

    # get all dates
    # Loop through the class's column names
    # then determine if each column is of the :date type.
    fields = klass.column_names.select do |k| 
                  klass.columns_hash[k].type == :date
                end

    # for each of the fields we'll use class_eval to
    # define the methods.
    fields.each do |field|
      klass.class_eval <<-EOF
        def formatted_#{field}
          #{field} ? #{field}.to_s(:date) : nil
        end

      EOF
    end
  end
end

Fügen Sie sie nun einfach in alle Modelle ein, die sie benötigen

 class CourseSection < ActiveRecord::Base
   include DateMethods
 end

Wenn das Modul eingebunden ist, wird es alle Datumsspalten untersuchen und die formatierten_ Methoden für Sie erzeugen.

Lernen Sie, wie das mit Ruby funktioniert. Es macht eine Menge Spaß.

Allerdings muss man sich fragen, ob dies notwendig ist. Ich persönlich halte es nicht für notwendig, aber wie gesagt, es hat Spaß gemacht, es zu schreiben.

-b-

2 Stimmen

Warum verwenden Sie collect und compact für das Array und nicht select?

1 Stimmen

Sie haben Recht, .select wäre hier besser geeignet. Ich habe festgestellt, dass .collect.compact manchmal schneller ist, auch wenn es nicht so aussieht, aber in diesem Fall ist .select die viel bessere Wahl. Danke, dass Sie das bemerkt haben. Ich habe mich auf die schwierigen Dinge konzentriert und die einfachen Dinge übersehen.

0 Stimmen

+1 Interessante und lustige Sachen. Es wäre besser, wenn Sie die Antwort (hier auf SO) korrigieren würden, um die Kommentare von Chris aufzunehmen.

11voto

workmad3 Punkte 24502

Für mich sieht es eher wie etwas für eine Hilfskraft aus. Versuchen Sie dies in der Hilfe Ihrer Anwendung:

def formatted_date(date)
   date ? date.to_s(:date) : nil
end

Die Formatierung gehört nicht wirklich in das Modell (aus genau dem Grund, den Sie entdeckt haben... es ist lästig, so einen allgemeinen Code in jedes Modell einzubauen).

Wenn Sie wirklich tun wollen, wie Sie aber sagen, dann was Sie tun könnten, ist monkeypatch die ActiveRecord-Superklasse und fügen Sie die Funktion, die Sie in dort wollen. Sie wäre dann für alle Ihre Modelle verfügbar. Beachten Sie, dass Monkeypatching zu unvorhersehbarem und undefiniertem Verhalten führen kann, die Verwendung erfolgt auf eigene Gefahr! Außerdem ist es ziemlich hakelig :)

class ActiveRecord::Base
   def formatted_start_date
      start_date ? start_date.to_s(:date) : nil
   end
end

Fügen Sie diese Methode einfach an einer Stelle ein, die ausgeführt wird, bevor irgendetwas anderes in Ihrer Anwendung ausgeführt wird, und die Methode wird dynamisch zur Basisklasse Ihrer Modelle hinzugefügt, so dass sie für die Verwendung verfügbar ist.

Oder Sie könnten ein Mixin für alle Ihre Modelle erstellen, aber das scheint ein bisschen übertrieben für eine einzige Methode.

0 Stimmen

Okay, lassen Sie uns annehmen, dass es angemessen war, die Formatierung in das Modell zu setzen, oder dass ich etwas anderes als die Formatierung mit jedem einzelnen Datumsfeld in meiner Anwendung tun möchte, wie würde ich es tun?

0 Stimmen

Yeah, aber die "start_date" Teil ist hier hart codiert, ich muss dies für alle Datumsfelder in der app zu tun, Sie könnte aufgerufen werden, start_date, end_date, term_date, finish_date, Datum, etc.. wie ich die Unterklasse für alle Datumsspalten überprüfen und dann eine dynamische Methode für jede schreiben?

0 Stimmen

Das weiß ich nicht... es klingt nur wie eine schlechte Idee :P

0voto

Eine Antwort auf Ihren Kommentar: Sie können gemeinsamen Code/Funktionalität in Module extrahieren, die Sie in eine Klasse einbinden (ich glaube, das nennt man mixin?) oder Sie können sich für Unterklassen entscheiden. Ich glaube nicht, dass Unterklassen der richtige Weg sind, wenn es sich nur um gemeinsame Funktionen handelt, die Sie in Ihre Objekte aufnehmen wollen, und nicht um eine echte Vererbungssituation.

Werfen Sie einen Blick auf Hier finden Sie weitere Informationen über Module und Ruby .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X