在Ruby on Rails中查看nil

时间:2010-05-01 07:04:23

标签: ruby-on-rails error-handling

我一直在使用Rails已经有一段时间了,我发现自己经常做的一件事就是在显示之前检查我的视图代码中的某个属性或对象是否为nil。我开始怀疑这是否总是最好的主意。

到目前为止,我的理由是,由于我的应用程序依赖于用户输入,因此可能会发生意外情况。如果我从编程中学到一件事,那就是用户输入程序员没想到的东西是运行时错误的最大来源之一。通过检查零值,我希望回避这一点并让我的观点优雅地处理问题。

事情是,我通常由于各种原因在我的模型或控制器代码中有类似的无效或无效的值检查。我不会在最严格的意义上称它为代码重复,但它似乎并不是很干。如果我已经在我的控制器中检查了nil对象,那么我的视图是否只是假设对象真的不是零?对于可以显示为零的属性,每次检查都是有意义的,但对于对象本身,我不确定什么是最佳实践。

以下是我所谈论的简化但典型的例子:

控制器代码

def show
    @item = Item.find_by_id(params[:id])

    @folders = Folder.find(:all, :order => 'display_order')

    if @item == nil or @item.folder == nil
        redirect_to(root_url) and return
    end
end

查看代码

<% if @item != nil %>
    display the item's attributes here

    <% if @item.folder != nil %>
        <%= link_to @item.folder.name, folder_path(@item.folder) %>
    <% end %>
<% else %>
    Oops! Looks like something went horribly wrong!
<% end %>

这是个好主意还是只是愚蠢?

5 个答案:

答案 0 :(得分:7)

您的示例代码已重新制作:

控制器代码。 (我假设这是ItemsController)

def show
  # This will fail with 404 if item is not found
  # You can config rails to pretty much render anything on Error 404
  @item = Item.find(params[:id])

  # doesn't seem to be used in the view
  # @folders = Folder.find(:all, :order => 'display_order')


  # this is not needed anymore, or should be in the Error 404 handler
  #if @item == nil or @item.folder == nil
  #  redirect_to(root_url) and return
  #end
end

查看代码,因为控制器确保我们有@item

#display the item's attributes here

<%= item_folder_link(@item) %>

帮助代码:

# display link if the item has a folder
def item_folder_link(item)
  # I assume folder.name should be a non-blank string
  # You should properly validate this in folder model
  link_to( item.folder.name, folder_path(item.folder) ) if item.folder
end

无论如何,我试着让观点变得非常简单。通常,如果我在视图中看到循环和条件,我会尝试将它们重构为帮助程序。

答案 1 :(得分:6)

不,你应该使用

<% if @item.nil? %>

例如

@item1=nil
if @item1.nil? ### true
@item2 = ""
if @item2.nil? ### false
@item3 = []
if @item3.nil? ### false
@item4 = {}
if @item4.nil? ### false

要检查对象是空的,如果它是假,空或空白字符串。

使用

<% if @item.blank? %>

参考: - this

例如

@item1=nil
if @item1.blank? #### true
@item2 = ""
if @item2.blank? #### true
@item3 = []
if @item3.blank? #### true
@item4 = {}
if @item4.blank? #### true

答案 2 :(得分:2)

不要忘记在Rails 2.3中添加的.try。这意味着您可以调用以下内容:

@object.try(:name)

如果@object为零,则不会返回任何内容。这可能是sameera207创意的内置解决方案。

理想情况下,您不应该将nil对象发送到视图中 - 但是并不总是可以避免。

答案 3 :(得分:1)

我个人认为,如果您在视图中检查nil(我认为因为视图是最终的表示层nil应该在该级别进行检查),您不希望在控制器中检查它。 (但这不适用于所有地方)

我建议你创建一个方法来检查nil(使它变得很干)并传递你的对象并检查它是否为零

类似的东西:

def is_nil(object)
 object.nil? ? '':object 
end 

并将其添加到应用程序控制器中并使其成为帮助程序(以便您可以在控制器和视图中使用它)

helper_method :is_nil - 将此行添加到应用程序控制器中)

现在您可以传递要检查的对象是否为零。

欢呼声,

sameera

答案 4 :(得分:0)

您的控制器负责决定要呈现的视图。如果您可以验证您的控制器在没有item或item_folder的情况下永远不会呈现此特定视图,那么您无需检查nil值。

通过可以验证我的意思是你有测试/规范来检查为nil项和item_folders呈现哪个视图。