9

I would like to call controller action from rake task. My question is what method is the best to prepare http request? Thanks for all tips.

Edit: Have someone another tip? I tried this and not work:

controller_obj = Controller.new
controller.your_method

I got this exception:

rake aborted!
uninitialized constant Controller

Edit2: I tried:

sess = ActionController::Integration::Session.new
sess.post('/route', 'codes=3')

But I got (I have require 'action_controller/integration' in rake file) :

rake aborted!
cannot load such file -- action_controller/integration
user2239655
  • 830
  • 2
  • 11
  • 28
  • what do you want to do? the controller should handle requests, your task is not a real request, it looks like you need something else but it's not clear because you didn't say what you really want to do – arieljuod Apr 09 '14 at 15:16
  • Temporary I need to call this controller from rake task. So I need simulate http request. And how to simulate POST request? Or GET with params – user2239655 Apr 09 '14 at 15:37
  • 1
    that's "HOW" you want to do it, but what do you want? why do you need to simulate a post or get request? maybe you need something else, it's not normal to call a controller action inside a task – arieljuod Apr 09 '14 at 16:16
  • It is simple. I have to add Products data and I want to send to controller some parameters and next create entity in DB. In the nearest future I will create view with some form and I will use this controller. But now I would like to send some data from rake task to controller and add entity to DB. It is no matter how but I would to have this data in my controller. – user2239655 Apr 09 '14 at 16:49
  • you can't do that, you have to move the logic to a model and maybe some logic in the task and your controller and your taks will have a similar (but different) code, your are trying to use a controller for something that it's not for – arieljuod Apr 10 '14 at 01:59

3 Answers3

13
task :use_controller_method_in_rake => :environment do
  session = ActionDispatch::Integration::Session.new(Rails.application)
  session.get "/foo"
  session.post "/bar", {my_post_params: 'foobar'}
end
chris finne
  • 2,321
  • 22
  • 17
  • Thanks for that! And BTW, please note that now the recommended way of getting such session is http://api.rubyonrails.org/classes/ActionDispatch/Integration/Runner.html#method-i-open_session, although I wasn't able to make it work in the 5 minutes I dedicated for it. So your method is still better. – dimitarvp Jun 22 '15 at 11:55
  • If you're using devise, you'll need to sign in first: https://stackoverflow.com/questions/4929078/how-to-sign-in-a-user-using-devise-from-a-rails-console – daino3 Jun 14 '16 at 17:27
9

You should move that action's behavior to a model class, then use that action with the instance of that model class. This is the standard approach.

move controller/action to a model class (Recommended). In your rake task, do the following....

model_obj = Model.new
model_obj.your_instance_method

And still you want to call controller action then you should create an instance of your controller in your rake task and call that action with that instance(if that method is an instance method.)

controller_obj = Controller.new
controller.your_method
Alok Anand
  • 3,346
  • 1
  • 20
  • 17
  • It is temporary solution. In the nearest future I will create view for this case, but now I would like to prepare controller. controller_obj = Controller.new <- I don't know that It will work because I have to call controller using http request (I thing maybe I'm wrong) – user2239655 Apr 08 '14 at 13:48
1

Thanks @chris-finne, that was very helpful. Note that session.response.body is where you can access the results. Here's an method I'm using in a rake task:

def api_json_get(url, params={})
  @rails_session ||= ActionDispatch::Integration::Session.new(Rails.application)
  @rails_session.get(url, { :format => :json }.merge(params))
  JSON.parse(@rails_session.response.body)
end

Notice I'm memoizing the session object since it's quite slow to instantiate and I'm calling this method many times.

Randomibis
  • 61
  • 1
  • 3