14

What I want to do:

In a model.rb, in after_commit, I want to run rake task ts:reindex

ts:reindex is normally run with a rake ts:index

fivetwentysix
  • 7,379
  • 9
  • 40
  • 58

5 Answers5

36

If you wish this rake code to run during the request cycle then you should avoid running rake via system or any of the exec family (including backticks) as this will start a new ruby interpreter and reload the rails environment each time it is called.

Instead you can call the Rake commands directly as follows :-

require 'rake'

class SomeModel <ActiveRecord::Base

  def self.run_rake(task_name)
    load File.join(RAILS_ROOT, 'lib', 'tasks', 'custom_task.rake')
    Rake::Task[task_name].invoke
  end
end

Note: in Rails 4+, you'll use Rails.root instead of RAILS_ROOT.

And then just use SomeModel.run_rake("ts:reindex")

The key parts here are to require rake and make sure you load the file containing the task definitions.

Most information obtained from http://railsblogger.blogspot.com/2009/03/in-queue_15.html

David Parker
  • 128
  • 2
  • 13
Steve Weet
  • 28,126
  • 11
  • 70
  • 86
  • Will this slow down the request? It would be better to put it into a worker right? – Strawberry Apr 15 '13 at 08:13
  • This will almost certainly slow down the request. I make no comment on whether he should do this or not as I don't know his application. I was just helping with the particular question as to "How" he should call rake from within Rails, not whether doing so is a good idea. – Steve Weet Apr 15 '13 at 13:56
  • Did this work for you? I've set it up, don't get any errors, but I don't see the result of the task anywhere, that is the task doesn't seem to be executed. – kakubei Dec 06 '13 at 15:35
  • 1
    Actually I found out you need to use `.execute` instead of `.invoke` for it to work, at least for me. – kakubei Dec 06 '13 at 15:52
  • Note you may need to call `Rake::Task.clear` followed by `::Application.load_tasks `before rake tasks will be loaded in your runtime environment. – Anthony E Mar 30 '16 at 00:28
  • Rather than manually loading the task file, you can simply do `Rails.application.load_tasks` – Stephen Apr 06 '17 at 15:28
4

This code automagically loads the Rake tasks for your Rails application without you even knowing how your application is named :)

class MySidekiqTask
  include Sidekiq::Worker

  def perform
    application_name = Rails.application.class.parent_name
    application = Object.const_get(application_name)
    application::Application.load_tasks
    Rake::Task['db:migrate'].invoke
  end
end
snrlx
  • 4,987
  • 2
  • 27
  • 34
3

I had this same issue and couldn't get the accepted answer to work in my controller with a Rails 4 project due to a load file error. This post gave me a working solution:

def restart_search
   require 'rake'
   spec = Gem::Specification.find_by_name 'thinking-sphinx'
   load "#{spec.gem_dir}/lib/thinking_sphinx/tasks.rb"
   Rake::Task["ts:stop"].execute
   Rake::Task["ts:start"].execute
   respond_to do |format|
     format.js { head :ok }
   end
end
littleforest
  • 2,057
  • 21
  • 29
3
require 'rake'
RailsApp::Application.load_tasks
class SomeModel <ActiveRecord::Base
  def self.run_rake(task_name)
    load File.join(Rails.root, 'lib', 'tasks', 'custom_task.rake')
    Rake::Task[task_name].invoke
  end
end

And then just use SomeModel.run_rake("ts:reindex").

Bowdzone
  • 3,827
  • 11
  • 39
  • 52
Uday kumar das
  • 1,615
  • 16
  • 33
-7

Have you tried `rake ts:reindex`?

jordinl
  • 5,219
  • 1
  • 24
  • 20