铁轨 + Haml:从部分返回会以某种方式删除表单标签
这是很长的,是的,我很抱歉。但我想澄清一下,因为这个问题很奇怪。
我有一个服务条款模式,每当用户不接受我们的服务条款 (TOS) 时就会出现。出于此处的目的,JavaScript 被关闭,并且呈现的内容严格是 html/css。因此,如果将页面分为 3 层,则为:底层 = 他们看到的页面(即事件页面),中间层:半不透明的覆盖层,顶层(主/可见)层:带有术语的模式其中的服务协议表格。该表单只是一个接受复选框和提交按钮。
我注意到 TOS 无法正常工作,但似乎是随机出现的。然后我注意到它被破坏了,但仅在我的活动页面(/event/foo)上,即使相同的部分负责显示服务协议条款,无论它们出现在网站上的哪个位置。因此,对于任何其他页面,例如 /group/bar,都会显示相同的 TOS 模式并且可以正常工作。
然后我意识到问题是我的 HTML 中缺少表单标签!刚刚走了。
因此,退一步来说,所涉及的 (HAML) 代码很简单:
%div#accept_tosC
%b Before form_for
- form_for @current_user do |form|
%b After form_for
%div#tosC= render :partial => 'general/terms'
%div.left
= render :partial => 'shared/user/tos_form_element'
%div.right
= image_submit_tag "/images/buttons/submit_100x20.png", :id => 'submit', :name => 'submit'
对于我们的 /events/foo 页面,生成的 HTML 如下所示:
<div id="accept_tosC">
<b>before form_for</b>
<div style="margin: 0pt; padding: 0pt;"><input type="hidden" value="put" name="_method"><input type="hidden" value="44c2bf7a64fc59baa3fc7129167f0e2c3e96abb6" name="authenticity_token"></div>
<b>after form_for</b>
这里明显的问题是“Before form_for”和“After form_for”是否会变成文档中,为什么表单标签 form_for 没有创建?
对于不同的页面,例如 /groups/foo,我们得到的正是我们所期望的:
<div id="accept_tosC">
<b>before form_for</b>
<form method="post" id="edit_user_595" class="edit_user" action="/users/595"><div style="margin: 0pt; padding: 0pt;"><input type="hidden" value="put" name="_method"><input type="hidden" value="44c2bf7a64fc59baa3fc7129167f0e2c3e96abb6" name="authenticity_token"></div>
<b>after form_for</b>
我将其跟踪到“底层”代码内的单个部分井(他们请求的页面,而不是 TOS 覆盖层)。这部分内容可能对任何特定个人可见,也可能不可见,因此我们必须检查用户是否可以查看此页面。其结果保存在变量 can_view 中:
:ruby
#some processing to set page info and can_view
return unless can_view
%div#statsC
...and so on...
这就是我的代码的样子,并且表单标签没有渲染。通过进行以下更改,表单元素标记按预期在所有页面中显示:
:ruby
#some processing to set page info and can_view
- if can_view
%div#statsC
...and so on...
因此问题是:为什么从部分返回会阻止表单元素标记成为文档的一部分?
This is lengthy, yes, I apologize. But I want to be clear because this issue is so odd.
I have a terms of service modal that comes up whenever a user has not accepted our terms of service (TOS). For the purposes here, javascript is turned off and what is rendered is strictly html/css. So the page, if thought of in 3 layers, is: bottom layer = page they came to see (i.e. an event page), middle layer: a semi-opaque overlay, top (primary/visible) layer: a modal with the terms of service agreement form in it. This form is simply an accept checkbox and submit button.
I noticed that the TOS was not working properly, but at seemingly random times. Then I noticed that it was broken but only on my event page (/event/foo) even though the same partial is responsible for showing the terms of service agreement no matter where they show up on the site. So for any other page, like /group/bar, the same TOS modal would show up and would work fine.
I then realized that the problem was that the form tag was missing from my HTML! Just gone.
So, taking a step back, the (HAML) code in question is simply:
%div#accept_tosC
%b Before form_for
- form_for @current_user do |form|
%b After form_for
%div#tosC= render :partial => 'general/terms'
%div.left
= render :partial => 'shared/user/tos_form_element'
%div.right
= image_submit_tag "/images/buttons/submit_100x20.png", :id => 'submit', :name => 'submit'
For our /events/foo page, the generated HTML look like this:
<div id="accept_tosC">
<b>before form_for</b>
<div style="margin: 0pt; padding: 0pt;"><input type="hidden" value="put" name="_method"><input type="hidden" value="44c2bf7a64fc59baa3fc7129167f0e2c3e96abb6" name="authenticity_token"></div>
<b>after form_for</b>
The obvious question here is if 'Before form_for' and 'After form_for' make it into the document, why doens't the form tag form_for creates?
For a different page, say /groups/foo, we get exactly what we would expect:
<div id="accept_tosC">
<b>before form_for</b>
<form method="post" id="edit_user_595" class="edit_user" action="/users/595"><div style="margin: 0pt; padding: 0pt;"><input type="hidden" value="put" name="_method"><input type="hidden" value="44c2bf7a64fc59baa3fc7129167f0e2c3e96abb6" name="authenticity_token"></div>
<b>after form_for</b>
I tracked it down to a single partial well inside the code for the "bottom" layer (the page they requested, not the TOS overlay). This partial in question may or may not be viewable to any given individual so we have to check if the user can view this page. The result of that is held in the variable can_view:
:ruby
#some processing to set page info and can_view
return unless can_view
%div#statsC
...and so on...
This is what my code looked like and the form tag did not render. By making the following change, the form element tag showed up as expected for all pages:
:ruby
#some processing to set page info and can_view
- if can_view
%div#statsC
...and so on...
So here is the question: Why would returning from a partial prevent a form element tag from becoming part of the document?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
简而言之,模板以神秘的方式工作,并且
return
在其中使用通常不安全。长的答案是,在幕后,模板被编译成 Ruby 方法,这些方法构建 HTML 代码字符串并返回该代码。我猜测,通过返回而不返回正确的代码,您会导致某些事情变得混乱并丢弃
form_for
连接到的字符串。The short answer is that templates work in mysterious ways, and
return
is just generally not safe to use within them.The long answer is that, behind the scenes, templates are compiled into Ruby methods that build up a string of HTML code and return that code. I'm guessing that by returning without returning the proper code, you're making something go haywire and discard the string that the
form_for
is concatenating to.