Run rake task in controller
Asked Answered
S

4

83

I'd like to run a rake task in my controller. Is there any way to do this?

Sanmiguel answered 23/7, 2009 at 7:18 Comment(4)
Ryan Bates covers a couple of ways in RailsCasts Episode #127.Barling
railscasts.com/episodes/127-rake-in-backgroundSaldana
try this >> system "rake task_name"Ping
@Ping yes you are right, this working well with me, system('rake task_name')Anatolia
S
65

I agree with ddfreynee, but in case you know what you need code can look like:

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

You can require 'rake' and .load_tasks in an initializer instead.

Semicircle answered 30/3, 2012 at 13:25 Comment(7)
Where would I find out what my "application name" is?Americana
@pxdleif It's in config/application.rb as the module name about 12 lines down, assuming you're using Rails.Ayakoayala
You can also reference your application by calling Rails.applicationLapides
This works great! Just so it's clear for others, this method is for synchronous calling of rake tasks (page does not render until rake is done). For async usage, use call_rake from this rails cast: railscasts.com/episodes/127-rake-in-backgroundEstreat
Actually after a bit more work, my app on Rails 3.2.13 only needed the Sample::Application.load_tasks line. If i include the Task.clear line my app works until I call the first rake, then it gives me an error about a custom override I made for doc:app. But that's just my appEstreat
what if params[:talk] is equal to "db:drop"?Curbing
Is this open as new thread? I've added in my controller and task is initialized but controller function will not respond untill rake task completed.Osterman
A
62

I don't find it good style to call a rake task in code. I recommend putting the code for the task that you want to execute somewhere outside a rake task, and have the rake task call this code.

This not only has the advantage of being easy to call outside rake (which is what you want), but it also makes it much easier to test the rake task.

Astonishment answered 23/7, 2009 at 7:49 Comment(7)
+1 I concur: this is a perfect example of things that should be refactored and called in two different ways.Tso
railscasts.com/episodes/127-rake-in-background Seems an excellent reason to run a rake..Saldana
Where would a good "somewhere" be for "somewhere outside the rake task"?Opheliaophelie
@Opheliaophelie if it's related to models, put it in the model class. if it's related to something else, create a new file that holds them.Vannoy
Service Objects. blog.engineyard.com/2014/…Dikdik
In my case I needed to run a task from a 3rd party lib, so I couldn't refactor it (without going through the trouble of forking, etc)Phenice
@ddfreyne What about if your services are tasks with dependencies? Doesn't it make sense to use rakes dependency management inside of your rails app instead of writing an own implementation?Premaxilla
G
25

Instead of trying to call a rake task in a controller, call a service objects that contains whatever logic you are trying to execute.

class SomeController < ApplicationController
  def whatever
    SomeServiceObject.call
  end
end

...and then, assuming you are talking about a custom rake task, have it call the service object as well:

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

In case you are not familiar with service objects, they are just plain old ruby classes that do a specific job. If you are trying to call some of the default rake tasks (ie: db:migrate) I would highly recommend not doing that sort of thing from a controller.

Goldoni answered 1/3, 2016 at 21:10 Comment(1)
This concept is very straight forward. it works great! I am not adding code in SomeServiceObject. I am writing in model with self and calling from rake task like this: User.subscribe_to_fcmBrotherinlaw
T
14

You can do this in your controller:

%x[rake name_task]

with: name_task is the name of your task

Traps answered 19/8, 2011 at 14:37 Comment(4)
how do you pass environment to it?Koppel
i would never shell out to rake from my controller in production.Enterogastrone
@Enterogastrone when you answer or comment can you also explain your reasoning and not just make an assertion (that a controller in production shouldn't call rake tasks)? This would help people understand your reasoning instead of just knowing what you wouldn't do (but not hearing your explanation as to why).Ovular
@Ovular shelling out means that Rake will execute in another process. This means it will launch a new ruby interpreter. It's also a possibility that injection can occur which leads to arbitrary commands being executed (a few typos away from doing that).Vannoy

© 2022 - 2024 — McMap. All rights reserved.