Using this railscast http://railscasts.com/episodes/127-rake-in-background?autoplay=true as an example/inspiration (i.e. I’m not trying to implement the rails cast code, just use it as an inspiration), I tried to move a mailer, that was triggered by an after_create callback in the user.rb model, into a rake task, so it would run in the background. The mailer was working before I moved it into a rake task, but it’s not working anymore.
Instead of calling the mailer from the User.rb model, which it was how it was set up originally (see the commented out code in user.rb), I instead call the rake task, which then invokes the UserMailer.welcome_email method.
In the original code, “self” was submitted (from User.rb) as a parameter to the method welcome_email(user) in user_mailer.rb. In my attempt to turn it into a rake task, I assigned “self” to USER_INSTANCE, which is supposed to be picked up in the mailer.rake as ENV[“USER_INSTANCE”]. This was also suggested by the railscast.
Somewhere along the way it’s not working. Any ideas?
User.rb
after_create :send_welcome_email
def send_welcome_email
system "rake :send_mailing USER_INSTANCE=self &" #note the & forks the task
#UserMailer.welcome_email(self).deliver <-- how it was originally.
end
mailer.rake
desc "Send mailing"
task :send_mailing => :environment do
UserMailer.welcome_email(ENV["USER_INSTANCE"]).deliver #moved from user.rb to here but now with environment variable instead of parameter
end
unchanged User_mailer.rb
class UserMailer < ActionMailer::Base
default :from => "blahblah@gmail.com"
def welcome_email(user)
mail(:to => user.email, :subject => "Invitation Request Received")
end
end
currently you are doing this
system "rake :send_mailing USER_INSTANCE=self &"which is the same as going to the command line and typing
rake :send_mailing USER_INSTANCE=self &self is just a literal string, I think what you are trying to do is this
system "rake :send_mailing USER_INSTANCE=#{self} &"but that will end up being the equivalent of running this on the command line
rake :send_mailing USER_INSTANCE=<User::xxxxx>rake won’t serialize this into your User ActiveRecord object;
when you shell out with system there is no relation to the calling code
an alternative – your rake task could take an integer – user_id and then access the record via User.find
but it gets more complicated as after_create is going to be running in a transaction so once your rake task runs it may or may not have finished that transaction
I would advise against trying to re-invent a way to do background processing in rails, there are already good tried and true solutions available
see http://railscasts.com/?tag_id=32 for some options