application.html.erb
中包含导航栏。因为对于某些页面,例如注册页面,我需要在导航栏中放置其他代码,我已经排除了这些页面以通过application.html.erb
显示导航栏,而是将其包含在各自的视图页面中。请参阅下面的代码。
在注册表单中输入无效数据时会出现问题。然后控制器方法呈现new
。但是,application.html.erb
似乎并未认识到current_page仍为signup_path
,因此未应用该异常,因为该页面上未显示导航栏。因此,当它呈现新的时,导航栏会显示两次:按application.html.erb
的顺序显示一次,按视图页面本身的顺序显示一次。
为什么在无效表单条目上呈现新内容时,是否看到它仍然在signup_path
上?我应该如何调整我的代码,以便在那种情况下它不会显示导航栏两次?是否有一种方法可以在<%= yield special code if any %>
和application.html.erb
中将<% special_code %> <% end special_code %>
包含在将此特殊代码传递给application.html.erb
的视图页面中?
在application.html.erb中我有:
<% unless current_page?(signup_path) %>
<nav class="banner">
<%= render partial: "shared/header" %>
</nav>
<% end %>
在我的注册页面视图中:
<nav class="banner">
<%= render partial: "shared/header" %>
Additional code that needs to be within 'nav' for this page
</nav>
控制器方法:
def create
@user = User.new(user_params)
if @stakeholder.save
flash[:success] = "A confirmation email has been sent to you."
redirect_to root_url
else
render 'new' ###This is where it goes wrong!
end
end
答案 0 :(得分:1)
您可以使用content_for
和yields
在布局中创建视图可以覆盖的默认值。
# layouts/application.html.erb:
<% if content_for?(:banner) %>
<%= yield(:banner) %>
<% else %>
<div id="banner">
<h1>This is the default...</h1>
</div>
<% end %>
/users/signup.html.erb:
<%- content_for :banner, flush: true do -%>
<!-- move along, nothing to see here -->
<%- end -%>
这里的优点是你最终不会将你的布局变成条件的鸟巢。您可以轻松地从视图中将任何您想要的内容注入到布局中。
缺点是你必须使用带有HTML注释的愚蠢黑客来覆盖块以显示任何内容,因为content_for?
修剪了块。 content_for
对片段捕获也不好看。
我在unless current_page?(signup_path)
无法正常工作之前没有触及此问题,因为render 'new'
并没有神奇地将您带到新的操作。实际上,current_path是/users
,因为从表单POST到该URL。
它只是告诉rails找到一个名为'new'的模板并渲染它。
更正版本将是:
<% unless controller_name == 'users' && ['new', 'create'].include?( action_name) %>
<nav class="banner">
<%= render partial: "shared/header" %>
</nav>
<% end %>
答案 1 :(得分:-1)
你完全正确。这是出错的地方
render 'new' ###This is where it goes wrong!
这里发生了什么
new
操作,该操作呈现new
模板create
操作create
操作中,您在验证失败时呈现new
模板而不是create
所以基本上用户不再在new
页面上,而是在create
页面上,其中包含从new
呈现的视图。
最简单的解决方案是将标头的期望更改为new
和create
操作,因为您重定向成功,因此您将无法使用它。