ruby-on-rails – 在Ruby或Ruby on Rails中使用控制流的异常情况是不错的做法?

我正在阅读敏捷Web开发与Rails(第4版),我已经找到以下代码
class ApplicationController < ActionController::Base
  protect_from_forgery

  private

  def current_cart
    Cart.find(session[:cart_id])
  rescue ActiveRecord::RecordNotFound
    cart = Cart.create
    session[:cart_id] = cart.id
    cart
  end
end

由于我是一名Java开发人员,我对该部分代码的理解或多或少是以下内容

private Cart currentCard(){
  try{
    return CartManager.get_cart_from_session(cartId)
  }catch(RecordNotFoundEx e){
    Cart c = CartManager.create_cart_and_add_to_session(new Cart())
    return c;    
  }
}

那是什么让我感到异常处理用于控制正常的应用程序流程(当用户第一次访问Depot应用程序时,缺少购物车是完全正常的行为).

如果有Java书籍,他们会说这是一件非常糟糕的事情,而且很有道理:错误处理不应该被用作控制语句的替代品,对于读取代码的人来说,这是一种误导.

有没有什么好的理由为什么这样的做法在Ruby(Rails)中是合理的?这是Ruby的常见做法吗?

解决方法

Rails在使用异常方面绝对不一致.如果没有找到对象,find将引发异常,但是为了保存,您可以选择所需的行为.最常见的形式是:
if something.save
  # formulate a reply
else
  # formulate an error reply,or redirect back to a form,or whatever
end

即保存返回true或false.但也有保存!这引发了一个异常(在方法名称的末尾添加一个感叹号是一个Rubyism,用于显示一个方法是“危险的”或破坏性的,或者简单地说它具有副作用,确切的含义取决于上下文).

为什么find引发异常有一个有效的原因,但是如果RecordNotFound异常冒泡到顶层,它将触发404页面的渲染.由于您通常不会手动捕获这些异常(在Rails应用程序中您很少看到救援ActiveRecord :: RecordNotFound),您可以免费获得此功能.在某些情况下,当某个对象不存在时,您需要执行某些操作,在这种情况下,您必须捕获该异常.

我不认为术语“最佳实践”实际上意味着什么,但是我的经验是,异常不用于控制Ruby中的流程,而不是Java或任何其他使用的语言.鉴于Ruby没有检查异常,所以您一般处理异常.

最后是解释.由于find最常见的用例是检索对象以显示它,并且该对象的URL将由应用程序生成,所以很可能是不能找到对象的特殊情况.这意味着应用程序正在生成到不存在的对象的链接,或者用户手动编辑了URL.也可能是对象已被删除,但是它的链接仍然存在于缓存中,或者通过搜索引擎,我会说这也是一种特殊情况.

该参数适用于在您的示例中使用,即使用ID.还有其他形式的查找(包括许多find_by_ *变体)实际搜索,并且那些不引发异常(然后在Rails 3中有哪些,它替代了在Rails 2中的许多用途).

我不是说使用例外作为流程的控制是一件好事,只是发现引发异常并不一定是错误的,而你的具体用例不是常见的情况.

相关文章

validates:conclusion,:presence=>true,:inclusion=>{...
一、redis集群搭建redis3.0以前,提供了Sentinel工具来监控各...
分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣...
上一篇博文 ruby传参之引用类型 里边定义了一个方法名 mo...
一编程与编程语言 什么是编程语言? 能够被计算机所识别的表...
Ruby类和对象Ruby是一种完美的面向对象编程语言。面向对象编...