1

我们的 Rails (3.0.14) 应用程序具有用户配置文件,用户可以在其中选择是否要接收 HTML 格式的电子邮件。为了保持干燥,我只想为所有邮件 (HTML) 设置一组模板,然后在 text/plain 部分使用我自己的字符串扩展名dehtml(基本上strip_tags带有一些格式修改)。另外,我想保持邮件代码干燥。

到目前为止,我们的邮件方法如下所示:

def signup_confirmation(user)
  @user = user
  mail(:to => @user.email, :subject => ..., ...)
end

1. DRY 模板:如果可能,我希望避免创建 200 个额外的邮件模板,并从 HTML 模板自动创建 text/plain 部分。这是基本思想(dehtml是我自己的字符串扩展):

def signup_confirmation(user)
  @user = user
  mail(:to => @user.email, :subject => ..., ...) do |format|
    format.html
    format.text { render(:file => 'signup_notification.html').dehtml }
  end
end

但是,这会因“缺少模板”错误而失败。我如何告诉 Rails 在这两种情况下都使用 HTML 模板?我尝试追加:formats => :html:handler => :html但这没有帮助。

我现在没有解决方案。有任何想法吗?

2:DRY mailer 方法: 由于我们的用户应该能够决定他们是否想要拥有 HTML,所以上面的方法看起来像

def signup_confirmation(user)
  @user = user
  attachments.inline["email-header.jpg"] = File.read(...) if @user.wants_html
  mail(:to => @user.email, :subject => ..., ...) do |format|
    format.html if @user.wants_html
    format.text { render(:file => 'signup_notification.html').dehtml }
  end
end

总之,这使每种方法的 LOC 增加了三倍。我想尽可能地把它干掉(因为它必须被插入到至少 200 个邮件方法中)。一个想法是编写我自己的mail方法(让我们称之为mymail)就像

def mymail(user, p={})
  attachments.inline["email-header.jpg"] = File.read(...) if user.wants_html
  mail(p) do |format|
    format.html if user.wants_html
    format.text
  end
end

(暂时忽略上面的文本模板问题)然后将每个调用更改mailmymail,如

def signup_confirmation(user)
  @user = user
  attachments.inline["email-header.jpg"] = File.read(...) if @user.wants_html
  mymail(user, { :to => @user.email, :subject => ..., ... })
end

这行得通。但这是好的做法吗?我在哪里最好放mymail- 在帮手?

欢迎任何见解和建议!

4

1 回答 1

1

很久以前,我做了与您的第一个解决方案非常相似的事情。我真的不记得为什么会这样,但这对我有用:

def my_mail
  mail(:to => @user.email ...) do |format|
    format.text { convert_html_to_plain(__method__) } # first text
    format.html                                       # then html
  end
end

def convert_html_to_plain(method)
  old_formats = self.formats
  self.formats = ["html"]
  rendered = render "#{method}", :layout => false
  self.formats = old_formats

  # strip tags, reformat, etc. from rendered
  rendered << render(:partial => "plaintext_footer", :locals => {:user => @user}, :formats => [:text] )
end
于 2012-10-28T02:04:25.957 回答