我有一个标题链接到我的application.html.erb,如下所示:
<header class="unselectable">
<h2 class="float_left">
<% if @user.try(:errors).present? %>
<%= render 'shared/error_messages' %>
<% else %>
<%= @title %>
<% end %>
</h2>
<nav class="round">
<ul>
<% if logged_in? %>
<li><%= link_to "Home", current_user %></li>
<li><%= link_to "Settings", edit_user_path %></li>
<li><%= link_to "Log out", logout_path %></li>
<% else %>
<li><%= link_to "Log in", login_path %></li>
<% end %>
</ul>
</nav>
</header>
这一切都很好,除非加载的页面没有@user变量(例如about或logout页面),在这种情况下我得到这个:
undefined method `errors' for nil:NilClass
我该如何使这项工作?我尝试更改逻辑以呈现标题unless
@user.errors.any?
,但这也不起作用。我确定这是一个简单的修复,但我无法弄明白!
编辑添加了建议的修补程序(在上面的标题部分中更新),现在出现此错误:
No route matches {:action=>"edit", :controller=>"users"}
似乎来自edit_user_path
答案 0 :(得分:3)
您可以使用方法.try(:something)
:
<% if @user.try(:errors).present? %>
<%= render 'shared/error_messages' %>
<% else %>
<%= @title %>
<% end %>
如果@user
为nil
,则.try(:errors)
不会引发错误。
.present?
方法也适用于nil
:
>> nil.present?
#=> false
>> false.present?
#=> false
>> [].present?
#=> false
>> ''.present?
#=> false
>> 'bonjour'.present?
#=> true
>> ['bonjour'].present?
#=> true
.present?
是.nil?
和.empty?
.present?
实际上是.blank?
答案 1 :(得分:1)
你可以改编成这样:
<header>
<h2 class="float_left">
<% if @user.try(:errors).try(:any?) %>
<%= render 'shared/error_messages' %>
<% else %>
<%= @title %>
<% end %>
</h2>
...
</header>
或者将errors_any?
添加到模型:
class User
def errors_any?
self.try(:errors).try(:any?)
end
end
对此:
<header>
<h2 class="float_left">
<% if @user.try(:errors_any?) %>
<%= render 'shared/error_messages' %>
<% else %>
<%= @title %>
<% end %>
</h2>
...
</header>
答案 2 :(得分:1)
我非常怀疑您的部分中@user
需要在您的应用程序布局中呈现,因此需要在应用程序的每个页面中。我认为这根本不是好设计,因为现在你依赖于应用程序的所有视图中的全局变量。
我认为你真正想要使用的是flash。在这种情况下,您需要application.html.erb
中的类似内容。
<% flash.each do |key, value| %>
<%= content_tag :div, value, class: key %>
<% end %>
这应该在适当的控制器操作中设置,然后才能呈现视图,以便根据刚刚发出的请求显示错误消息。
如果您的错误消息来自您的模型,那么这应该是实际生成这些错误消息的一部分。通常,这是对控制器中的create
或update
操作的调用。在这种情况下,当您的验证未通过时,您应该使用表单呈现error_messages
部分,并使用模型对象再次呈现表单。
<%= form_for @user do |f| %>
<%= render 'shared/error_messages', :object => f.object %>
<!-- and so on -->
<% end %>
通过这种方式,您可以确信@user
对象始终可用于部分呈现而没有任何错误,因为我们明确地将对象传递给部分本身,并且正在使用正确的呈现部分上下文。在部分中使用@users
等同于使用全局变量,因此整个应用程序依赖于该全局变量存在。
现在使用部分中的局部变量@user
访问object
对象(或者您决定最终命名它的任何内容)。
<% object.errors.full_messages.each do |message| %>
<li>* <%= message %></li>
<% end %>