我围绕名为status的模型创建了一个多态关联。
某些联系人将拥有与之关联的状态。许多人不会。
如果我在没有状态时尝试调用状态,则会出现错误。现在,即使我没有为模型创建状态,它仍然可以运行if-end块中的任何内容。
这是我正在尝试的,但它不起作用:
<% if !@status.nil? %>
<p>Status: <%= @status.find(:last).status %></p>
<% end %>
在控制器中,它定义如下:
@status = Contact.find(@contact).statuses
顺便说一句,也开放使代码更具可读性和干燥性。
答案 0 :(得分:0)
让它干嘛:
@statuses = @contact.statuses
和
<% unless @statuses.nil? %>
<p>Status: <%= @status.last.status %></p>
<% end %>
如果我理解您的代码以及您正在尝试正确执行的操作,这对您有帮助吗?
<% if @statuses.length > 0 %>
<p>Status: <%= @status.last.status %></p>
<% end %>
答案 1 :(得分:0)
一种选择是不必检查是否存在状态,通过为所有联系人(创建联系人时)提供无效状态的默认状态。
你可以把它称为Null Object习惯用法:你在其他地方使用null(C,C ++,Java)或NULL(SQL)的对象 - 这实际上是Smalltalk用nil做的事情; nil是一个特殊对象,是UndefinedObject类的一个实例。
这个成语的优点是你不必检查“对象不存在”条件并进行特殊处理。这样可以实现更清晰的代码,并且更加面向对象,因为您的Null Object实例(而不是调用代码)可以确定调用其方法时要执行的操作。
这是一个Java示例,使用责任链模式。责任链基本上意味着拥有一个处理程序列表,每个处理程序都处理一些事情(命令)或将其传递给链中的下一个处理程序。我们将创建一个Null Object处理程序,当它被要求处理某些东西时它什么也不做。
首先,一般合同:
interface Handler {
void handle( Command c ) ;
}
然后是Null Handler,带有(恐怖!)单身人士:
class NullHandler implements Handler {
public static void NullHandler singleton = new NullHandler();
void handle( Command c ) { /*no-op*/}
}
然后是每个其他类型的Handler的基类(这也使用了模板方法模式,这只是一个实现细节):
abstract class BaseHandler implements Handler {
private Handler next;
public BaseHandler( Handler next ) {
this.next = next ;
}
public BaseHandler() {
this( NullHandler.singleton ) ;
}
public void handle( Command c ) {
if( canHandle( c ) {
doHandle( c ) ;
} else {
next.handle( c ) ;
}
}
//Template Method hooks
abstract boolean canHandle( Command c ) ;
abstract void doHandle( Command c ) ;
}
所以我们得到的是有限的 - 我们可以next.handle( c ) ;
而不是if next != null next.handle( c ) ;
。但随着我们添加更多代码,价值变得更加明显。
假设我们要打印我们的责任链。一种方法是在代码中外化迭代链,每次测试以查看next == null。
但更好,更面向对象,我们可以让Chain自己做。再次,在BaseHandler
的打印中,我们打印该实例的名称,然后调用next
的打印方法。 NullHandler中的print
方法不会打印任何内容,或者可能是“链末端”。
答案 2 :(得分:0)
我实际想出了这个:
<% unless @status.empty? %>
<p>Status: <%= @status.find(:last).status %> <%= @status.find(:last).created_at.to_s(:long) %></p>
<% end %>
答案 3 :(得分:0)
Contact.statuses返回数组的开放父级问题 - 总之。如果联系人没有状态,则数组为空([]) - 但不是nil。
我发现您现在正在使用empty?
。
我建议通过移动到模型来使其更加干燥。例如,采用这种简单的方法:
class Contact < ActiveRecord::Base
...
def last_status
@last_status ||= statuses.last
end
end
使用此功能,您无需计算控制器上的@statuses
变量。
它还会在statuses.last
上缓存@last_status variable
,因此只调用一次statuses.last。如果您不希望发生这种情况,请删除@last_status ||=
部分。
然后您的观点可以按照您最初的预期或多或少地完成:
<% unless @contact.last_status.nil? %>
<p>Status: <%= @contact.last_status.status %> <%= @contact.last_status.created_at.to_s(:long) %></p>
<% end %>