稍后我将解决检查报告是否已发送的问题,但首先我将讨论如何从 ActiveAdmin 调用控制器操作的问题。
虽然您可以ReportsController#send_status通过创建一个ActionController::Base::ReportsController然后调用所需的方法来调用,例如
ActionController::Base::ReportsController.new.send_status
这不是一个好主意。您可能应该重构它以解决几个潜在问题。
app/controllers/reports_controller.rb:
class ReportsController < ApplicationController
  ... # rest of controller methods
  def send_status
    if current_user # or whatever your conditional is
      ReportMailer.status_email(current_user).deliver
      response = :ok
    else
      response = :bad_request
    end
    head response
  end
end
app/models/user.rb:
class User < ActiveRecord::Base
  ... # rest of user model
  def reports_for_date(date)
    reports.for_date(date)
  end
end
app/mailers/reports_mailer.rb
class ReportsMailer < ActionMailer::Base
  ... # rest of mailer
  def status_email(user)
    @user = user
    @date = Date.today
    @reports = @user.reports_for_date(@date)
    ... # rest of method        
  end
end
这显然可以进一步重构,但提供了一个不错的起点。
需要考虑的重要一点是,此控制器操作不会异步发送电子邮件,因此为了并发和用户体验,您应该强烈考虑使用排队系统。使用我提供的示例,DelayedJob 将是一个简单的实现(查看 DelayedJob RailsCast)。
至于检查报告是否已发送,您可以实现一个 ActionMailer 观察者并注册该观察者:
这要求User模型具有 BOOLEAN 列status_sent并且用户具有唯一的电子邮件地址。
lib/status_sent_mail_observer.rb:
class StatusSentMailObserver
  self.delivered_email(message)
    user = User.find_by_email(message.to)
    user.update_attribute(:status_sent, true)
  end
end
config/intializer/setup_mail.rb:
... # rest of initializer
Mail.register_observer(StatusSentMailObserver)
如果您使用的是DelayedJob(或几乎任何其他排队系统),您可以实现一个回调方法,以便在作业完成时调用(即发送状态电子邮件),以更新用户的列。
如果您想跟踪每天的状态消息,您应该考虑创建一个Status属于User. 每次用户发送电子邮件时都可以创建状态模型,让您可以通过检查是否存在状态记录来检查电子邮件是否已发送。这个策略是我会认真考虑采用的一个简单的策略status_sent专栏上采用的策略。
tl;dr ActionController::Base::ReportsController.new.send_status & 实现一个观察者,它更新跟踪状态的用户列。但你真的不想那样做。像我上面提到的那样研究重构。