【发布时间】:2014-03-08 09:39:46
【问题描述】:
是否可以从 cron 作业中调用 ActionMailer?我们正在使用 Rails 3。
理想情况下,cron 作业会触发脚本从数据库中读取用户,将这些用户和一些变量传递给 ActionMailer 类以触发电子邮件。
这在 Rails 3.2.12 中可行吗?
【问题讨论】:
标签: ruby-on-rails ruby-on-rails-3 cron smtp actionmailer
是否可以从 cron 作业中调用 ActionMailer?我们正在使用 Rails 3。
理想情况下,cron 作业会触发脚本从数据库中读取用户,将这些用户和一些变量传递给 ActionMailer 类以触发电子邮件。
这在 Rails 3.2.12 中可行吗?
【问题讨论】:
标签: ruby-on-rails ruby-on-rails-3 cron smtp actionmailer
如果其他一切都失败了,您可以创建一个正常的控制器操作并让 cronjob 使用 curl 调用它。
否则,您的 Rails 应用程序脚本文件夹中的任何脚本都可以从命令行使用 rails runner script/myscript.rb 启动,并且可以完全访问所有 Rails 功能。
【讨论】:
您可以使用rails r (rails runner) 在您的 rails 应用程序中运行脚本。它运行它,在执行此操作之前在您的 rails 应用程序的完整上下文中加载,因此您的所有模型等都可用。我经常使用它。例如,
rails r utilities/some_data_massaging_script.rb
对于 cron,您显然需要为其提供应用程序的完整路径。
老式的方法是:
require "#{File.dirname(__FILE__)}/../config/environment.rb"
在脚本的顶部(当然,根据应用程序中脚本的子目录级别调整路径的相对位),然后使用 ruby 运行脚本,但rails r 使这变得不必要。
【讨论】:
是的,这是可能的。您可以使用rake 命令调用任务。你的任务可能是这样的:
# lib/tasks/cron.rake
namespace :cron do
desc "Send account emails"
task deliver_emails: :environment do
accounts_for_delivery = Account.where(condition: true)
# ... whatever logic you need
accounts_for_delivery.each do |account|
Postman.personalized_email_for(account).deliver
end
end
end
您的邮件程序和相应的视图可能如下所示:
# app/mailers/postman.rb
class Postman < ActionMailer::Base
def personalized_email_for(account)
@account = account
mail to: account.email
end
end
# app/views/postman/personalized_email_for.text.haml
= @account.inspect
现在您可以设置 crontab 来运行您的 rake 任务,就像您执行 rake 任务一样。我建议您使用 whenever gem,它确实提供了一种为您的应用程序定义 cronjobs 的好方法,如下所示:
# config/schedule.rb
every 6.hours do
rake 'cron:deliver_email'
end
所以现在 cronjob 定义已绑定到您的应用程序。它也适用于部署之间的Capistrano。您还可以在任务中传递变量或执行系统命令。
【讨论】: