Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 在Rails视图中避免nil_Ruby On Rails_Model View Controller_Null - Fatal编程技术网

Ruby on rails 在Rails视图中避免nil

Ruby on rails 在Rails视图中避免nil,ruby-on-rails,model-view-controller,null,Ruby On Rails,Model View Controller,Null,我肯定已经有人问过了,但我找不到答案 我有一个项目模型,它与我的客户模型有关系。客户机有名称,但项目不一定有客户机 在我看来,我有这样的代码: <%=h project.client && project.client.name %> 因为如果项目没有客户端,那么尝试访问project.client.name会导致NoMethodError(nil没有名为name的方法) 问题是,在视图中进行这种“零”检查是可以接受的,还是我应该寻找另一种方法来解决它?我认为这

我肯定已经有人问过了,但我找不到答案

我有一个项目模型,它与我的客户模型有
关系。客户机有名称,但项目不一定有客户机

在我看来,我有这样的代码:

<%=h project.client && project.client.name %>

因为如果项目没有客户端,那么尝试访问
project.client.name
会导致NoMethodError(
nil
没有名为
name
的方法)


问题是,在视图中进行这种“零”检查是可以接受的,还是我应该寻找另一种方法来解决它?

我认为这是完全可以接受的-这是视图逻辑,您或多或少会根据是否有数据来决定是否显示视图的一部分。

我一直遇到这种情况,是的,这很烦人。即使应该永远不会有零,我继承的脏数据有时也会触发它

您的解决方案是处理它的一种方法。您还可以向
Project
添加一个名为
client\u name
的方法,该方法显示客户机名称(如果存在),但是您将模型链接在一起的次数超过了一些人的建议

def client_name
  client && client.name
end
您也可以创建一个帮助器方法来完成此操作,但最终可能会编写很多帮助器方法。:)

正如Skilldrick在下面提到的,这对于添加默认字符串也很有用:

def client_name
  client ? client.name : "no client"
end
只用

project.client.try(:name)

我的黑客解决方案是产生一个块并挽救错误。许多人会说,使用救援作为逻辑是非常糟糕的形式。只是不要在你需要知道什么时候是零,什么时候不应该是零的地方使用它

在应用程序_helper.rb中:

  def none_on_fail
      begin
          return yield
      rescue
          return "(none entered)"
      end
  end
然后在视图中:

<%= none_on_fail { project.client.name }  %>


然后,可以根据需要将方法链接到尽可能深的位置,并且可以在任何方法上使用,但如果模型/关系/方法存在,则会掩盖其他潜在问题。我会把它等同于用火焰喷射器取出碎片。非常有效,如果使用不当,会带来痛苦的后果。

我认为这些检查通常可以通过一点思考来消除。这有助于保持视图代码更干净,更重要的是,将逻辑排除在视图层之外,这是一种最佳实践。一些模板引擎不允许视图中有任何逻辑

至少有两种情况。假设您有一个依赖于实例变量的
show
操作。我想说,如果没有找到记录,控制器不应该通过重定向或其他方式呈现html。如果视图中有数组的循环,请使用
@array.each do | a | end
,这样它就不会计算数组是否为空。如果您确实希望在视图中使用默认应用程序,请尝试从配置文件加载它,例如
@page_title | |#{@APP_config['page_title']}
(请参阅)。请记住,您可能希望稍后更改这些字符串,例如翻译UI


在这两种情况下,可以避免进行状态检查和使用
try
。如果可能的话,我会尽量避开他们。如果您无法避免它们,我会将条件检查放在视图帮助器中,并为其添加一个帮助器单元测试,以验证(并记录)这两个代码路径。

您可以在
项目
类中使用
委托
,这样您就可以遵守“只与直接朋友交谈”的规则

project.rb

class Project
  delegate :name, to: :client, prefix: true, allow_nil: true    
end
因此,通过这种方式,项目对象将知道在哪里询问客户的姓名:

#You can now call
project.client_name

中查看有关
委托的更多信息,我忘记了一个…:)但是,当您深入5-6个模型时,它仍然会变得很麻烦:(@Tass你对得墨忒尔法的看法是对的,但我认为这不是正确的实施方法,请参阅我下面的帖子。@dombesz但你的方法会使本地化变得更困难。如果你想尊重得墨忒尔,请发出警告或类似警告。这在某些情况下(例如,如果你想要“无客户”这样的默认名称)绝对有用。另一个不使用三元运算符的默认字符串实现:
client.name | |“无客户端”
当然,有人可能会争辩说,既然最初的问题是讨论使用纯mvc模型,那么通过在模型中添加默认显示字符串,您可能正在向模型中注入更多的视图逻辑,不是吗?这就是为什么我会像提问者那样做。但是,这都是风格,这也很有效:)。我只是不想假设我所做的每一个视图都需要相同的默认字符串,你知道吗?是否有一个gem或其他东西可以自动处理这种情况?