Führen Sie die Rechenaufgabe im Controller aus

76

Ich möchte eine Rechenaufgabe in meinem Controller ausführen. Gibt es eine Möglichkeit, dies zu tun?

user143482
quelle
Ryan Bates behandelt in RailsCasts Episode # 127 einige Möglichkeiten .
Simone Carletti
7
versuchen Sie dies >>system "rake task_name"
Bongs
@Bongs ja du hast recht, das funktioniert gut mit mir, system ('rake task_name')
Astm

Antworten:

62

Ich stimme ddfreynee zu, aber falls Sie wissen, wie Sie Code benötigen, kann dies aussehen:

require 'rake'

Rake::Task.clear # necessary to avoid tasks being loaded several times in dev mode
Sample::Application.load_tasks # providing your application name is 'sample'

class RakeController < ApplicationController

  def run
    Rake::Task[params[:task]].reenable # in case you're going to invoke the same task second time.
    Rake::Task[params[:task]].invoke
  end

end

Sie können stattdessen 'rake' und .load_tasks in einem Initialisierer benötigen.

Grimmo
quelle
Wo würde ich herausfinden, wie mein "Anwendungsname" lautet?
pdxleif
@pxdleif Es ist config/application.rbals Modulname ungefähr 12 Zeilen weiter unten, vorausgesetzt, Sie verwenden Rails.
Tim Fletcher
2
Sie können Ihre Anwendung Referenz durch den Aufruf auchRails.application
declan
2
Das funktioniert super! Nur damit es für andere klar ist, dient diese Methode zum synchronen Aufrufen von Rake-Aufgaben (die Seite wird erst gerendert, wenn der Rake abgeschlossen ist). Verwenden Sie für die asynchrone Verwendung call_rake aus dieser Rails-Besetzung: railscasts.com/episodes/127-rake-in-background
portforwardpodcast
Nach etwas mehr Arbeit benötigte meine App auf Rails 3.2.13 nur die Zeile Sample :: Application.load_tasks. Wenn ich die Zeile Task.clear einbinde, die meine App funktioniert, bis ich den ersten Rake aufrufe, wird eine Fehlermeldung bezüglich einer benutzerdefinierten Überschreibung angezeigt, die ich für doc: app vorgenommen habe. Aber das ist nur meine App
portforwardpodcast
58

Ich finde es nicht gut, eine Rechenaufgabe im Code aufzurufen. Ich empfehle, den Code für die Aufgabe, die Sie ausführen möchten, irgendwo außerhalb einer Rechenaufgabe zu platzieren und die Rechenaufgabe diesen Code aufrufen zu lassen.

Dies hat nicht nur den Vorteil, dass es einfach ist, einen externen Rechen aufzurufen (was Sie möchten), sondern es erleichtert auch das Testen der Rechenaufgabe erheblich.

Denis Defreyne
quelle
6
+1 Ich stimme zu: Dies ist ein perfektes Beispiel für Dinge, die auf zwei verschiedene Arten überarbeitet und aufgerufen werden sollten.
James A. Rosen
7
railscasts.com/episodes/127-rake-in-background Scheint ein ausgezeichneter Grund, einen Rechen zu betreiben ..
baash05
4
Wo wäre ein gutes "irgendwo" für "irgendwo außerhalb der Rechenaufgabe"?
user456584
@ user456584 Wenn es sich um Modelle handelt, fügen Sie es in die Modellklasse ein. Wenn es sich um etwas anderes handelt, erstellen Sie eine neue Datei, die diese enthält.
2
In meinem Fall musste ich eine Aufgabe von einer Drittanbieter-
Bibliothek ausführen
18

Anstatt zu versuchen, eine Rake-Task in einem Controller aufzurufen, rufen Sie ein Serviceobjekt auf, das die Logik enthält, die Sie ausführen möchten.

class SomeController < ApplicationController
  def whatever
    SomeServiceObject.call
  end
end

... und dann, vorausgesetzt, Sie sprechen von einer benutzerdefinierten Rechenaufgabe, lassen Sie sie auch das Serviceobjekt aufrufen:

namespace :example do
  desc 'important task'
  task :important_task do
    SomeServiceObject.call
  end
end

Falls Sie mit Serviceobjekten nicht vertraut sind, handelt es sich lediglich um alte Ruby-Klassen, die einen bestimmten Job ausführen. Wenn Sie versuchen, einige der Standard-Rake-Tasks aufzurufen (z. B. db: migrate), würde ich dringend empfehlen, so etwas nicht von einem Controller aus auszuführen.

Jarrod Spiller
quelle
1
Dies ist eine sehr saubere Art und Weise. Vielen Dank.
Juliangonzalez
16

Sie können dies in Ihrem Controller tun:

%x[rake name_task]

mit: name_taskist der Name Ihrer Aufgabe

Olibouli
quelle
2
Wie geben Sie die Umgebung an sie weiter?
Serengeti12
4
Ich würde niemals in der Produktion von meinem Controller harken.
Herzog
21
@Duke Wenn Sie antworten oder kommentieren, können Sie auch Ihre Argumentation erläutern und nicht nur eine Behauptung aufstellen (dass ein Controller in der Produktion keine Rechenaufgaben aufrufen sollte)? Dies würde den Leuten helfen, Ihre Argumentation zu verstehen, anstatt nur zu wissen, was Sie nicht tun würden (aber Ihre Erklärung nicht zu hören, warum).
Matt
6
@Matt Shelling Out bedeutet, dass Rake in einem anderen Prozess ausgeführt wird. Dies bedeutet, dass ein neuer Ruby-Interpreter gestartet wird. Es besteht auch die Möglichkeit, dass eine Injektion auftritt, die dazu führt, dass beliebige Befehle ausgeführt werden (ein paar Tippfehler davon entfernt).