在用户指定的时间发送邮件并在 rails 错误中更新数据库中的状态

sending mail at user assigned time and updating status in database in rails error

我想在每个阶段的 remind_at 时间 send mail。我正在使用 whenever gem 来安排任务。有 user 个模型,其中包含 email 个具有角色经理的多个用户,并且每个经理都有 one_to_manyproject 的关联以及项目 has one_to_many 与 [=25] 的关联=].

在向每个用户发送电子邮件时,我想为每个用户更新阶段的属性 mail_status 并将邮件主题更改为 stage.name。我怎样才能实现这样的目标??

stage.rb

def check_project_activity
  current_date = Time.now.strftime("%Y-%m-%d").to_s
  @stages = Stage.all
  @stages.each do |stage|
    ProjectMailer.activity_reminder(stage).deliver and stage.mail_status = true and stage.save! if stage.remind_at.strftime("%Y-%m-%d").to_s == current_date
  end
end

schedule.rb

  every 1.day, at: '4:30 am' do
    runner 'stage.project_activity_check'
  end

activity_mailer.rb

  def activity_reminder(stage)
    @stage = stage
      mail(:to =>  User.joins(projects: :stages).where(role: 'manager', stages: { remind_at: Time.now.strftime("%Y-%m-%d") }).pluck(:email), :subject => "activity reminder " + stage.name)
  end

我参考了这个 post - Sending emails on user-selected dates

但是我的实现不起作用。

这是我使用的代码,但问题是它向所有用户发送一次电子邮件,但我想要动态更改是根据用户的电子邮件子集以及模板正文更改-

activity_reminder.rb

desc 'activity reminder email'
task activity_reminder_email: :environment do
  ProjectMailer.activity_reminder(self).deliver!
end

project_mailer.rb

  def activity_reminder(stage)
    @stage = stage
      mail(:to =>  User.joins(projects: :stages).where(role: 'manager', stages: { remind_at: Time.now.strftime("%Y-%m-%d") }).pluck(:email), :subject => "Project Activity Remainder")
  end

schedule.rb

  every 1.day, at: '4:30 am' do
    rake 'activity_reminder_email'
  end

它工作正常,但我希望电子邮件主题为 stage.name 根据每个用户,它还应该遍历每个任务并更新 stage.email_status 以执行任务。

我认为你可以做一些改变:

  • 您正在将 remind_at 值格式化为 Y-m-d 日期的字符串化版本,在这种情况下,您可以将它们作为日期进行比较。 to_date就够了。
  • 您可以过滤 SQL 查询中的行,而不是 select 过滤所有内容;将 remind_at 转换为日期并使用 RDBMS 函数获取当前日期,之后比较保持不变。
  • 保持不变,但您可能 select 您在查询中使用的确切列。这通常是首选,因此您可以得到您所需要的,仅此而已。
  • 首选 && 而不是 and,因为它们没有相同的优先级(&& 更高),这可能会导致您的代码不一致(这不是Python).
  • 您可以使用 update 而不是两行赋值。
def check_project_activity
  Stage.where('remind_at::date = CURRENT_DATE').each do |stage|
    ProjectMailer.activity_reminder(stage).deliver
    stage.update(mail_status: true)
  end
end

remind_at::date = CURRENT_DATE 是 PostgreSQL 特有的,但很容易适应。