在Ruby on Rails中检查视图中的nil值。

14

我已经使用Rails一段时间了,发现自己经常在视图代码中检查某些属性或对象是否为空值,然后再显示它们。我开始怀疑这样做是否总是最好的选择。

到目前为止,我的理由是,由于我的应用程序依赖于用户输入,意外情况可能会发生。如果从编程方面学到的一件事情是,用户输入的东西程序员没有考虑到是运行时错误的最大源头之一。通过检查空值,我希望能够避免这种情况,并使我的视图优雅地处理问题。

但实际上,在我的模型或控制器代码中通常出现类似的nil或无效值检查,原因各不相同。我不会严格称之为代码重复,但它似乎并不符合DRY原则。如果我已经在控制器中检查过空对象,那么在视图中假设该对象确实不为空,这样做是否可以?对于可以为空的属性,每次都检查是有意义的,但对于对象本身,我不确定什么才是最佳实践。

以下是一个简化但典型的示例:

控制器代码

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个回答

8
不,你应该使用:


<% if @item.nil? %>

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

检查对象是否为空,如果为false、空或仅由空格组成的字符串,则为空。

使用

<% if @item.blank? %>

参考文献: 这里

例如:

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

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

无论如何,我试图保持视图非常简单。通常,如果我在视图中看到循环和条件语句,我会尝试将它们重构为帮助程序。

2

不要忘记Rails 2.3中添加的.try方法。这意味着你可以调用以下类似的代码:

@object.try(:name)

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

理想情况下,您不应该将空对象发送到视图中 - 但是有时无法避免。


1

我个人认为,如果你在视图中检查nil(因为视图是最终的呈现层,应该在该层级别检查nil),你不想在控制器中检查它。(但这并不适用于所有地方)

我建议你创建一个检查nil的方法(使其更加DRY),传递你的对象并检查它是否为nil

类似于:

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

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

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

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

干杯,

萨米拉


0

你的控制器负责决定将渲染哪个视图。如果你可以验证,你的控制器永远不会在没有item或item_folder的情况下渲染这个特定的视图,那么你就不需要检查nil值。

通过“可以验证”,我是指你有测试/规范来检查哪个视图被渲染为nil项和item_folders。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接