【发布时间】:2014-06-03 09:31:11
【问题描述】:
我们使用 Amazon SES 发送电子邮件,这就是为什么我们使用 DelayedJob 发送所有可能很庞大的电子邮件的原因。 DelayedJob 将这些电子邮件排队等待发送,它们之间至少间隔一秒钟。
它通常工作正常,但我发现变量似乎缓存在 ActionMailer 模板中以及与其中一些电子邮件一起发送的生成的 PDF 中。 PDF 是使用 Prawn 生成的。
例如,假设我们所有的客户都有一个唯一的 ID,我向两个客户发送了一封电子邮件。第一个客户端的 ID 为 1234,第二个客户端的 ID 为 2345。发生的情况是两个客户端都收到一封电子邮件,其中 ID 为 1234。两封电子邮件都发给了正确的人,并且其他一些变量将正确呈现。
我最初认为这个问题与我的电子邮件模板中使用了帮助程序有关。我将分享一个例子:
<%- @extra_lines.each do |line|
if @interpolations
@interpolations.each do |key,value|
line = line.html_safe.sub "%{#{key}}", value.to_s
end
end %>
<p><%= line.html_safe %></p>
<%- end %>
我希望这是有道理的,@extra_lines 是一个变量,它包含我们的电子邮件的一些额外段落,这些段落是基于一组条件生成的。 @interpolations 的每个成员的value 包含在第二封电子邮件中重复的内容。在上述情况下,@interpolations 看起来像 {user_id: 1234}。
现在,并非所有变量都有这个问题。如果我只是渲染一个从 Mailer 类传递的变量,则不会发生这种情况。这就是为什么我担心我正在使用的一种辅助方法的输出被缓存的原因。更重要的是因为类似的行为发生在我的 PDF 类中。
所以我尝试通过生成一个启用了 DelayedJob 的新 Rails 应用程序来重现这一点,并创建了这个邮件:
class MyMailer < ActionMailer::Base
default from: "from@example.com"
def random_amount(arguments)
@extra_lines = arguments[:extra_lines]
@interpolations = arguments[:interpolations]
mail to: 'to@example.com'
end
end
此邮件模板:
<%- @extra_lines.each do |line|
if @interpolations
@interpolations.each do |key,value|
line = line.html_safe.sub "%{#{key}}", value.to_s
end
end %>
<p><%= line.html_safe %></p>
<%- end %>
还有这个控制器:
class RandomController < ApplicationController
def index
extra_lines = [
'Test line 1',
'Test line 2 with %{variable}',
'Test line 3'
]
10.times do
interpolations = {variable: rand(1..100)}
arguments = {extra_lines: extra_lines, interpolations: interpolations}
MyMailer.delay.random_amount(arguments)
end
render :text => "Master, I've scheduled mail for you."
end
end
这是尽可能接近“真实”应用程序的结果,它会导致向我发送 10 封具有唯一随机数量的电子邮件。因此,基本上,我无法重现该问题,而且更令人困惑的是,大部分时间它都能正常工作。
有没有人听过这件事?
【问题讨论】:
-
我在您的代码中注意到的第一件事是,在“邮件模板”中,您正在为@interpolations 执行每个循环,并将 line 设置为一个字符串。这意味着它只是循环中的最后一次迭代, vil 位于 line 变量中……这是设计使然吗?
-
您能详细说明一下吗?在每次迭代中,
line变量通过用value替换任何%{key}匹配来更新。@interpolations中的每个键都是唯一的。 -
只有
=每次迭代都会覆盖最后一次。因此,如果您想向您的 line 变量添加多个插值,您需要在@interpolations.each循环之前对其进行 decalere 并在循环内使用line += ..。否则 line 变量将只包含@interpolations.each的最后一次迭代的字符串 -
也许我误解了你在说什么,但请注意
line变量已经设置,我没有做line = somethingelse,但实际上line = line.sub(..)。每个@interpolations.each循环都会更新它。所以,最初它可以是Hello this is %{var1} and %{var2},在第一个循环之后它类似于Hello this is me and %{var2},将%{var1}替换为me,在第二个循环之后它可能是Hello this is me and you。 -
啊。对不起这是我的错!在那里快速阅读代码:)
标签: ruby-on-rails-3 caching actionmailer delayed-job prawn