如果你看erb -x -T - test.erb输出的代码:
#coding:ASCII-8BIT
_erbout = ''; _erbout.concat "<div class='row'>\n "
; _erbout.concat(( form.field_container :name do ).to_s); _erbout.concat "\n"
; _erbout.concat " "; _erbout.concat(( form.label :name, raw('Name' + content_tag(:span, ' *', :class => 'required')) ).to_s); _erbout.concat "\n"
; _erbout.concat " "; _erbout.concat(( form.text_field :name, :class => 'fullwidth' ).to_s); _erbout.concat "\n"
; _erbout.concat " "; _erbout.concat(( form.error_message_on :name ).to_s); _erbout.concat "\n"
; _erbout.concat " "; end ; _erbout.concat "\n"
; _erbout.concat "</div>\n"
; _erbout.force_encoding(__ENCODING__)
你可以看到在第三行,do 后面跟着一个)。 Ruby 期待一个 do…end 块,但得到一个右括号。这就是语法错误的直接原因。
erb 输出错误代码的原因是你使用了<%=,而你应该使用<%。将代码更改为此可以修复语法错误:
<div class='row'>
<% form.field_container :name do %>
<%= form.label :name, raw('Name' + content_tag(:span, ' *', :class => 'required')) %>
<%= form.text_field :name, :class => 'fullwidth' %>
<%= form.error_message_on :name %>
<% end %>
</div>
我无法运行此代码来测试它在我更改后是否输出它应该输出的内容,但erb 生成的代码看起来可以工作:
#coding:ASCII-8BIT
_erbout = ''; _erbout.concat "<div class='row'>\n "
; form.field_container :name do ; _erbout.concat "\n"
; _erbout.concat " "; _erbout.concat(( form.label :name, raw('Name' + content_tag(:span, ' *', :class => 'required')) ).to_s); _erbout.concat "\n"
# more...
编辑
由于这个解决方案显然确实破坏了输出,我研究了mu is too short 的建议。我检查了Erubis(Rails 3 uses by default)的行为是否与 ERB 不同。 erubis -x -T - test.erb输出的代码(带有原版,未经编辑的test.erb):
_buf = ''; _buf << '<div class=\'row\'>
'; _buf << ( form.field_container :name do ).to_s; _buf << '
'; _buf << ' '; _buf << ( form.label :name, raw('Name' + content_tag(:span, ' *', :class => 'required')) ).to_s; _buf << '
'; _buf << ' '; _buf << ( form.text_field :name, :class => 'fullwidth' ).to_s; _buf << '
'; _buf << ' '; _buf << ( form.error_message_on :name ).to_s; _buf << '
'; end
_buf << '</div>
';
_buf.to_s
第三行有完全相同的问题,erubis -x -T - test.erb | ruby -c 输出相同的语法错误。因此,ERB 和 Erubis 之间的差异可能不是问题所在。
我也试过语法检查这段代码from the official Rails documentation:
<%= form_for(zone) do |f| %>
<p>
<b>Zone name</b><br />
<%= f.text_field :name %>
</p>
<p>
<%= f.submit %>
</p>
<% end %>
它得到相同的语法错误。所以并不是说你的 ERB 代码写得不好;您的代码与该示例非常相似。
在这一点上,我最好的猜测是 erb 的 -x 标志,它将 ERB 模板转换为 Ruby 代码而不是直接评估它,它有缺陷,并且不支持它应该支持的某些功能。虽然现在我想起来了,但是当你输出一个本身输出文本的块的结果应该工作时,我很难想象究竟应该输出什么 Ruby 代码应该。每个输出应该在什么时候被写入——首先是结果,还是首先写入块内容?