让Actionmailer在rails3中发送过期任务列表

时间:2011-07-30 10:06:20

标签: ruby-on-rails actionmailer

我正在尝试通过cron向我的用户发送一封电子邮件,每个都有一份他们应有的任务列表。我可以向每个有过期任务的用户发送电子邮件。在我的电子邮件模板中,我可以显示所有逾期任务。我不能做的只是列出特定用户的任务。

首先,我创建了一个范围,用于查找具有适当任务的所有用户:

users.rb的

scope :tasksdue, lambda {
       joins("join tasks on tasks.user_id = users.id").
       where("tasks.dueddate >= ? AND tasks.status = ?", Date.today, false).
       group("users.id")
     }

同样在我的用户模型中,我找到并向这些用户发送电子邮件:

def self.send_reminders
         User.tasksdue.find_each do |user|
         UserMailer.deliver_task_due user 
       end
end

而且,在我看来,我有这个:

<!DOCTYPE html>
<html>
  <head>
    <meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
  </head>
  <body>
    <h1>Hello! <%= @user.name %></h1>

    <% User.listtasks.find_each do |task| %>
  <li> <%= task.tasks.title %> </li>
<% end %>

  </body>

问题在于应有的任务。我正在从我的用户模型调用范围:

 scope :listtasks, lambda {
   joins("join tasks on tasks.user_id = users.id").
   where("tasks.dueddate >= ? AND tasks.user_id = ? AND tasks.status = ?", Date.today, :id, false)       
}

使用这个,我收到一个错误:

  

的未定义方法`title'

我也试过从Tasks.rb调用

 scope :tasksdue, lambda { 
     where("dueddate >= ? AND user_id = ? AND status = ?", Date.today, Task.user_id, false)
  }

抱怨user_id。

我可以让它列出所有全球逾期任务,但不是每个用户。

我需要做什么才能列出每个用户的任务?

- 编辑---

根据以下@ ream88的建议,我创建了两个独立的范围,并在我的任务控制器中打开和逾期:

scope :overdue, lambda { where('dueddate >= ?', Date.today) }
scope :open, where(:status => false)

现在我不知道如何迭代这些。我在动作管理器模板中尝试了这个,但每个用户的电子邮件都是相同的......

<% Task.open.overdue.find_each do |task| %>
<%= task.title %>
<% end %>

如何在此请求中指定用户?

1 个答案:

答案 0 :(得分:3)

你在自己的功能上做了很多内置,为什么?我的意见:

has_many模型中创建User关联,并在belongs_to模型中创建相应的Task关联(如果尚未完成):

# user.rb
has_many :tasks

# task.rb
belongs_to :user

并将以下范围添加到Task

scope :overdue, lambda { where('dueddate >= ?', Date.today) }
scope :open, where(:status => false)

现在,您可以通过以下方式访问特定用户的逾期任务:user.tasks.open.overdue。 (您可以在Task模型中仅创建一个范围,包括两个搜索条件,但我的意见是将我的代码拆分为可能的最小部分。)


# mailer.rb
def task_due(user)
  @user, @tasks = user, user.tasks.open.overdue
  mail(:to => user.mail, :subject => 'Do your work! Dammit!') do |as|
    as.html { render('your/email/partial') }
    as.text { render('your/email/partial') }
  end
end

# your/email/partial.html.erb
<% @tasks.each do |task| %>
  <li><%= task %></li>
<% end %>

# your/email/partial.text.erb
<% @tasks.each do |task| %>
  * <%= task %>
<% end %>

# models/user.rb
def self.send_mails_to_lazy_users
  # Remind lazy user about their tasks!
  # This function should be called in a controller, after a specific button was pressed or in a background task, like delayed_job
  includes(:tasks).where(:tasks => ['duedate >= ? AND status = ?', Date.today, false]).each do |lazy_user|
    Mailer.task_due(lazy_user)
  end
end