質問

Is it possible to invoke ActionMailer from a cron job? We're using Rails 3.

Ideally, a cron job triggers a script to read users from a database, passes these users and some variables to an ActionMailer class to fire off emails.

Is this possible in Rails 3.2.12?

役に立ちましたか?

解決

Yes it is possible. You could use a task to invoke with the rake command. Your task could be something like this:

# 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

And your mailer and the corresponding view could look like this:

# 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

Now you can set the crontab to run your rake task just like you perform rake tasks. I recommend you use the whenever gem, that really provides a nice way to define cronjobs for your application that looks like this:

# config/schedule.rb
every 6.hours do
  rake 'cron:deliver_email'
end

So now the cronjob definitions are bound your application. It works well with Capistrano between deployments as well. You can also pass variables at your task or execute system commands.

他のヒント

If everything else fails you can just create a normal controller action and let the cronjob call it with curl.

Otherwise any script in your Rails apps script folder can be started with rails runner script/myscript.rb from the commandline and has full access to all Rails features.

You can use rails r (rails runner) to run a script in your rails app. It runs it, loading in the full context of your rails app before doing so, so all your models etc. are available. I use it a lot. For example,

rails r utilities/some_data_massaging_script.rb

From cron, you'd obviously need to give it the full path to your app.

The old-fashioned way was to have something like:

require "#{File.dirname(__FILE__)}/../config/environment.rb"

at the top of your script (adjusting the relative bit of the path depending on the subdirectory level of your script in your app of course) and then just run your script using ruby, but rails r makes that unnecessary.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top