Запустіть завдання граблі в контролері


78

Я хотів би запустити завдання граблі у своєму контролері. Чи є спосіб зробити це?


Райан Бейтс висвітлює кілька шляхів у RailsCasts Episode # 127.
Сімоне Карлетті


7
спробуйте це >>system "rake task_name"
Bongs

@Bongs та ви маєте рацію, це добре працює зі мною, система ( «граблі task_name»)
астма

Відповіді:


63

Я погоджуюся з ddfreynee, але якщо ви знаєте, що вам потрібно, код може виглядати так:

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

Натомість у ініціалізаторі можна зажадати 'rake' та .load_tasks.


Де б я дізнався, що таке моя "назва програми"?
pdxleif

@pxdleif Це config/application.rbім'я модуля знаходиться приблизно на 12 рядків вниз, припускаючи, що ви використовуєте Rails.
Тім Флетчер

2
Ви можете також посилатися на вашу заявку по телефонуRails.application
Деклан

2
Це чудово працює! Щоб зрозуміло це було для інших, цей метод призначений для синхронного виклику рейкових завдань (сторінка не відображається, поки не завершиться рейк). Для асинхронного використання, використання call_rake з цих рейок відливати: railscasts.com/episodes/127-rake-in-background
portforwardpodcast

Власне, після трохи більше роботи, моєму додатку на Rails 3.2.13 потрібен був лише рядок Sample :: Application.load_tasks. Якщо я включаю рядок Task.clear, моя програма працює, доки я не викликаю перший рейк, то це видає мені помилку про спеціальне перевизначення, яке я зробив для doc: app. Але це лише мій додаток
portforwardpodcast

59

Я не вважаю хорошим стилем називати рейк-завдання в коді. Я рекомендую помістити код для завдання, яке ви хочете виконати, десь поза завданням згрібання, і нехай виклик виклику цього коду.

Це не тільки має перевагу в тому, що легко викликати зовнішні рейки (що саме вам потрібно), але і значно полегшує тестування завдання на рейк.


6
+1 Я погоджуюсь: це чудовий приклад речей, які слід реконструювати та називати двома різними способами.
James A. Rosen

7
railscasts.com/episodes/127-rake-in-background Виглядає чудовою причиною запустити граблі ..
baash05

4
Де було б гарне "десь" для "десь поза грабельним завданням"?
user456584

@ user456584, якщо це пов'язано з моделями, віднесіть його до класу моделей. якщо це пов’язано з чимось іншим, створіть новий файл, який їх вміщує.

2
У моєму випадку мені потрібно було запустити завдання зі сторонньої бібліотеки, тому я не міг його
переформатувати (не зазнавши

18

Замість того, щоб намагатись викликати завдання rake у контролері, зателефонуйте об’єктам служби, що містять будь-яку логіку, яку ви намагаєтесь виконати.

class SomeController < ApplicationController
  def whatever
    SomeServiceObject.call
  end
end

... а потім, припускаючи, що ви говорите про спеціальне завдання згрібання, попросіть його також викликати об’єкт служби:

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

Якщо ви не знайомі з сервісними об'єктами, це просто звичайні рубінові класи, які виконують певну роботу. Якщо ви намагаєтеся викликати деякі завдання за замовчуванням (наприклад: db: migrate), я настійно не рекомендую робити подібні дії з контролера.


1
Це дуже чистий спосіб зробити це. Дякую.
juliangonzalez

17

Ви можете зробити це у своєму контролері:

%x[rake name_task]

with: name_task- це назва вашого завдання


2
як ви передаєте йому середовище?
serengeti12

4
я ніколи не хотів би згрібати свій контролер у виробництві.
Герцог

21
@Duke, коли ти відповідаєш чи коментуєш, чи можеш ти також пояснити свої міркування, а не просто стверджувати (що контролер у виробництві не повинен викликати рейкові завдання)? Це допомогло б людям зрозуміти ваші міркування, замість того, щоб просто знати, що ви не робите (але не чути вашого пояснення, чому).
Метт

6
Обстріл @Matt означає, що Rake виконає інший процес. Це означає, що він запустить новий інтерпретатор рубіну. Також є ймовірність того, що може статися ін’єкція, що призводить до виконання довільних команд (за кілька опечаток).
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.