【问题标题】:Rails how to create a method that can be used via browser and cron jobRails 如何创建可通过浏览器和 cron 作业使用的方法
【发布时间】:2012-12-29 00:33:11
【问题描述】:

我创建了一个名为 get_primary_email(user) 的方法,它位于我的 application_controller.rb 文件中。

现在我在我的应用程序以及调用使用 get_primary_email(user) 的方法的 cron 作业中都使用此方法

我的问题是,如果我将方法定义为:

def get_primary_email(user)
end

它在我的应用程序中运行良好,但 cron 作业出错。

如果我这样定义方法:

def self.get_primary_email(user)
end

我的 cron 作业有效,但通过浏览器调用 get_primary_email(user) 的每个方法都失败了。

如何在两个地方使用相同的方法?

编辑

schedule.rb

set :output, "#{path}/log/cron.log"

every 1.day, :at => "8:00pm" do
  runner "BirthdayRemindersController.send_birthday_email_reminders"
end

【问题讨论】:

  • 您是否在模型中定义“get_primary_email”?您能向我们展示一下代码以及您是如何设置 cron 作业的吗?
  • 不,这是我的 application_controller.rb 文件。我用作帮助用户获取主要用户的方法。每个用户最多可以有 3 封电子邮件,并且每封电子邮件都有一个布尔字段。
  • 最好的选择可能是将方法移动到一个单独的类并在那里调用它。将这样的东西放在模型上是很常见的,但它可以作为一个独立的类正常工作。
  • 你了解实例方法和类(静态)方法的区别吗?您将其称为应用程序中的实例方法和 cron 中的类方法。这是你的问题。我建议将此方法移动到模型中,然后创建一个用户演示器以将功能公开给控制器和 cron
  • 我对实例方法和类方法的区别有点熟悉。你能解释一下“用户演示者”是什么意思吗?

标签: ruby-on-rails ruby ruby-on-rails-3 cron whenever


【解决方案1】:

这通常通过设置 cron 作业来调用 rake 任务来完成。在 rake 任务中,您可以轻松调用 Rails 代码。

网上有很多例子。这是来自 SO 的一个:

A cron job for rails: best practices?

编辑——添加 Resqueue 代码和 Mailer 示例

用户.rb

class User

  scope :birthday_today, lambda { where('birthday = ?', Date.today) }

  def self.send_birthday_alerts
    self.birthday_today.each do |user|
      BirthdayAlertJob.enqueue(user.id)
    end
  end

  def get_primary_email
    ...
  end

end

jobs/birthday_alert_job.rb

class BirthdayAlertJob
  @queue = :birthday_alert

  def self.perform(u_id)
    user = User.find(u_id)
    UserMailer.birthday_alert(@user).deliver
  end
end

schedule.rb

every 1.day, :at => "8:00pm" do
  rake "users:send_birthday_alerts"
end

users.rake

namespace :users do
  desc "Queue up Birthday Alerts"
  task :send_birthday_alerts => :environment do
    User.send_birthday_alerts
  end
end

user_mailer.rb

class UserMailer < ActionMailer::Base

  def birthday_alert(user)
    mail(to: user.primary_email, subject: "Happy Birthday")
    ...
  end
end

这很接近,未经测试等。我知道您需要做的一件事是确保尚未向用户发送电子邮件。不知道你现在是怎么做的。另一列可以保存警报上次排队的时间。

【讨论】:

  • 我已经看过该链接几次。事实上,我在我的代码中使用了第二个示例。我已经用我的 schedule.rb 文件中的代码更新了我的问题,该文件来自when gem。
【解决方案2】:

根据您发布的内容,我建议如下:

lib/birthday_reminders.rb:

class BirthdayReminders
  def self.send_birthday_email_reminders
    # code ...
  end

  def self.primary_email_for(user)
    # code ...
  end
end

控制器/application_controller.rb:

class ApplicationController < ActionController::Base
  def get_primary_email(user)
    BirthdayReminders.primary_email_for(user)
  end
end

SOMEWHERE/schedule.rb:

set :output, "#{path}/log/cron.log"

every 1.day, :at => "8:00pm" do
  runner "BirthdayReminders.send_birthday_email_reminders"
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-04-25
    • 2022-09-25
    • 2011-11-29
    • 2017-07-06
    • 2016-09-27
    相关资源
    最近更新 更多