1

背景:由于电子邮件客户端(错误)处理样式的方式,在 Rails 邮件布局中,所有样式都需要为每个标签内联,因此布局很冗长。

因此,例如,如果您有一个由 3 个段落 (%p) 组成的具有相同样式的信息块,则该样式必须应用于五个段落中的每一个。

# example of  hard_coded_mailer_layout.html.haml
...
%p{style: "some very very long style declaration"}
  This sentence is about Foo.
%p{style: "the SAME REPEATED very very long style declaration"}
  This sentence is about Bar.
%p{style: "yes, again, the SAME repeated long style declaration"}
  This sentence is about FooBar.
...

所以现在假设文本是特定于帐户的并且来自视图(而不是被硬编码到布局中)。

如果它是已知的最大段落数(上例中为 3),则视图可以简单地指定 3 个 content_for 块(:foo、:bar 和 :foobar),并且布局可以有 3 个相应的产量(:foo、:bar 和:foobar) 像这样:

# example layout_yielding_3_blocks.html.haml
...
- if content_for?(:foo)
  %p{style: "some very very long style declaration"}
    = yield :foo
- if content_for?(:bar)
  %p{style: "the SAME REPEATED very very long style declaration"}
    = yield :bar
- if content_for?(:foobar)
  %p{style: "yes, again, the SAME repeated long style declaration"}
    = yield :foobar
...

# corresponding view
- content_for :foo do
  Your account has 2 Foos.
- content_for :bar do
  Your account has 8 Bars.
- content_for :foobar do
  Your account has 0 FooBars.
...

问题:如果您想将可变数量的段落传递给布局,但仍然让布局应用样式,该怎么办?有没有办法让视图指定一个包含 N content_for 元素的数组,以便布局可以简单地遍历它们?具体是这样的:

# desired view... is it possible?
- content_for :info[0] do
  Your account has 2 Foos.
- content_for :info[1] do
  Your account has 8 Bars.
- content_for info[2] do
  Your account has 0 FooBars.
...

这样布局可能如下所示:

#  desired corresponding layout, can something like this be done?
...
- yield(:info).each_with_index do |para, i|
  %p{style: "some very very long style declaration"}
    = (yield(:info))[i]

简单但有问题的方法:简单的做法是在视图中有一个content_for,其中包含所有 N 个段落,它们的相同样式重复 N 次,如下所示:

# current way of doing it (bad for 2 reasons below)
- content_for :all_info do
  %p{style: "some very very long style declaration"}
    Your account has 2 Foos.
  %p{style: "the SAME REPEATED very very long style declaration"}
    Your account has 8 Bars.
  %p{style: "yes, again, the SAME repeated long style declaration"}
    Your account has 0 FooBars.

但这很臭(如代码异味),因为(a)它非常不干燥,甚至更糟(b)现在内联样式分布在单个布局和可能使用该布局的数十个视图之间......如果你改变您需要在很多地方更改“样式”,或者将其他地方的样式定义为字符串或在email_para_style_info 其他地方命名为变量的常量。

4

1 回答 1

0

改为构建并使用视图助手。

module EmailHtmlHelper
  def account_message(content = nil, &block)
    content_tag :p, content, style: account_message_styles, &block
  end

  def account_message_styles
    %{
      font-size: 1.2em;
      color: #c0ffee;
    }.tr("\n", '')
  end
end

<%= account_message 'Your account has 2 Foos.' %>

<%= account_message do %>
  A longer, 
  more complex
  <span>message</span>
  <%= link_to 'here', foo_url %>
<% end %>

或者,如果您真的不希望 helper 中的样式(在这种情况下这是一个完全可以接受的地方),您只需点击视图中的样式并为每个实例使用它们:

<% "color: blue;".tap do |inline_styles| %>
  <%= content_tag :p, 'Status: Open', style: inline_styles %>
  <%= content_tag :p, 'Balance: $100', style: inline_styles %>
<% end %>

请注意,使用标签助手 likecontent_tag将适当地转义内容,这意味着您可以避免意外关闭引号的问题。

于 2017-02-16T03:43:17.837 回答