0

使用这个 railscast http://railscasts.com/episodes/127-rake-in-background?autoplay=true作为例子/灵感(即我不是试图实现 rails cast 代码,只是用它作为灵感) ,我试图将一个由 user.rb 模型中的 after_create 回调触发的邮件程序移动到一个 rake 任务中,这样它就会在后台运行。在我将它移入 rake 任务之前,邮件程序正在工作,但它不再工作了。

我没有从 User.rb 模型调用邮件程序,这是它最初的设置方式(参见 user.rb 中注释掉的代码),而是调用 rake 任务,然后调用 UserMailer.welcome_email 方法。

在原始代码中,“self”(来自 User.rb)作为参数提交给welcome_email(user)user_mailer.rb 中的方法。在我尝试将其转换为 rake 任务时,我将“self”分配给 USER_INSTANCE,它应该在 mailer.rake 中作为 ENV[“USER_INSTANCE”] 提取。railscast 也提出了这一点。

一路上的某个地方它不起作用。有任何想法吗?

用户.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

邮件程序.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

未更改 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

结尾

4

1 回答 1

1

目前你正在这样做

system "rake :send_mailing USER_INSTANCE=self &"

这与转到命令行并键入相同

rake :send_mailing USER_INSTANCE=self &

self 只是一个文字字符串,我认为您要做的是

system "rake :send_mailing USER_INSTANCE=#{self} &"

但这最终将等同于在命令行上运行它

rake :send_mailing USER_INSTANCE=<User::xxxxx>

rake 不会将其序列化到您的 User ActiveRecord 对象中;当您使用系统外壳时,与调用代码无关

另一种选择 - 你的 rake 任务可以采用一个整数 - user_id 然后通过 User.find 访问记录,但它变得更加复杂,因为 after_create 将在事务中运行,所以一旦你的 rake 任务运行,它可能已经完成,也可能没有完成交易

我建议不要尝试重新发明一种在 Rails 中进行后台处理的方法,已经有很好的尝试和真正的解决方案可用

有关一些选项,请参见http://railscasts.com/?tag_id=32

于 2012-05-12T20:57:34.200 回答