为什么人们不在Rails中的ActiveRecord.find周围包装开始/救援块?

时间:2010-07-29 21:14:36

标签: ruby-on-rails ruby

如果用户尝试提交表单或访问使用以下内容的服务:

Model.find(params[:id]) # if model does not exist, throw ActiveRecord::RecordNotFound

如果找不到实例,则抛出异常。然而,我很少看到人们在开始/救援块中包含该声明,即使您创建了一个脚手架,rails生成器也不会将开始/救援块中的查找调用包裹起来。

这是否有原因?

5 个答案:

答案 0 :(得分:4)

我认为这是因为最常见的情况是,如果你按照id来追踪一个对象并且它不存在那么这就是例外。异常会冒出来,rails将把它作为404处理,这通常是合适的。

如果是对象可能存在或不存在的情况,那么捕获异常或使用Model.find_by_id(params[:id])并检查nil对象都能很好地工作。

答案 1 :(得分:2)

一个原因可能是错误处理逻辑被传递给应用程序中的救援处理程序。

你的控制器:

def some_action
  @foo = Foo.find!(params[:id])
  # Exception will raise here ...
  # ...
end

然后指定

rescue_from ActiveRecord::RecordNotFound, :some_method_that_will_render_a_404

(请参阅this获取解释)

脚手架只是在短时间内获得某些东西的快捷方式,但根据经验,支架不适合生产

就个人而言,我没有看到太多代码至少没有进行基本验证。我认为这有点文化:如果你没有创建一个会引发错误的路线,你没有义务处理它。显然这远非理想,但我认为不是许多开发人员的优先事项。这主要取决于业务逻辑:它通常是正向的,即只考虑响应用户有效的操作。

答案 2 :(得分:0)

因为它更容易调用:

Model.find_by_id(params[:id])

如果没有找到记录,则返回nil

答案 3 :(得分:0)

因为你想要fail early。你越早发现错误,就越早解决问题。

答案 4 :(得分:0)

我见过这样的代码:

def add_to_cart
  begin
    product = Product.find(params[:id])
  rescue ActiveRecord::RecordNotFound
    logger.error("Attempt to access invalid product #{params[:id]}")     
    redirect_to_index("Invalid product")
  else
    @cart = find_cart
    @cart.add_product(product)      
  end
end