2016-05-09 4 views
1

Mit ActiveSupports extensions to Numeric kann Folgendes geschrieben werden, um zwei Minuten zu erhalten: 2.minutes.Erstellen einer einzelnen Zeiteinheit (Minute, Woche usw.) mit ActiveSupport

Es gibt jedoch Situationen, in denen nur wenige Zeiteinheiten wichtig sind. Angenommen, es ist eine Aufgabe, die Anwendung jedes ein Tage laufen kann, Woche oder Monat, je nach gewissen Eingang:

@frequency = :day # can be any of the following: [:day, :month, :week] 

Active die Erweiterungen Numeric Mit naiver, könnten wir dies tun, um zu bestimmen, wann die Aufgabe ausgeführt werden soll :

def run_every 
    1.send(@frequency) 
end 

, die die days Instanzmethode in Numeric (die day Methode ist ein Alias) nennen.

In diesem Szenario interessiert uns nur ein Minute, Tag, Woche, Monat, Jahr, etc. Gibt es eine schönere Möglichkeit, eine andere Zeiteinheit als die beschriebene zu instanziieren?

+0

"Minute" ist eine * Einheit * Zeit, während "1 Minute" * a * Dauer ist. Bist du sicher, dass du '1.minute' und nicht nur': minute' willst? – Stefan

+0

@Stefan das ist vollkommen richtig, und ja, ich bin mir sicher. Ich verwende diese Frequenz, um etwas für die spätere Ausführung zu planen (Sidekiqs 'perform_in', die eine' Zeit' oder eine 'Dauer' benötigt). – brito

Antwort

1
# can be any of the following: [:day, :month, :week] 

ich stattdessen einen Hash verwenden würde, so etwas wie:

DURATIONS = { day: 1.day, week: 1.week, month: 1.month }.freeze 

def run_every 
    DURATIONS[@frequency] 
end 
+0

Können Sie erklären warum? Ist es schneller als Senden wegen des Einfrierens oder etwas? – Caillou

+1

@Caillou 'freeze' dient nur dazu, Änderungen zu verhindern. Ich versuche, 'send' /' public_send' im Allgemeinen zu vermeiden, da es beliebige Nachrichten delegieren kann, die zu schwer zu verfolgenden Fehlern führen können. Mit einem expliziten Hash kann der Rückgabewert der Methode gesteuert werden. 'run_every' gibt entweder' ActiveSupport :: Duration' oder 'nil' zurück. – Stefan

+0

Ich verstehe. Dann könnten wir beide Tricks verwenden, um etwas wie "DAUER = [: Tag,: Woche,: Jahr]" zu erzeugen und es als Bestätigung der Frequenz zu verwenden, während wir noch senden, um die Dauer zu erzeugen. – Caillou

1

TL; DR: Diese Antwort sagt nur „Sie haben es richtig“

Es scheint eine ziemlich gute Nutzung der send Methode zu sein: Sie haben eine Zeiteinheit erhalten auf einer Frequenz abhängig (Tag, Monat , Jahr), so mit send auf einem numerischen mit der Häufigkeit, wie der Name der Methode scheint mir der perfekte Anwendungsfall send.

EDIT: Wie Jordan sagte, sollten Sie einfach public_send anstelle von send, als eine gute Gewohnheit verwenden. Das liegt daran, dass Sie mit send auf private Methoden zugreifen können, was normalerweise nicht empfohlen wird.

+1

Man sollte 'public_send' statt' send' verwenden (nur als gute Angewohnheit), aber ansonsten stimme ich zu. Sehen Sie sich die Quelle der [Numeric] (https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/numeric/time.rb) ActiveSupport-Erweiterungen und [ActiveSupport :: Duration] (https : //github.com/rails/rails/blob/master/activesupport/lib/active_support/duration.rb) wir können sehen, dass es keinen saubereren Weg gibt, eine Duration zu instanziieren. –

+0

Ich stimme zu. Ich bearbeite die Antwort mit Präzisierungen über 'public_send'. – Caillou

Verwandte Themen