当找不到id时,整个控制器的一般救援 – RoR

我偶然发现了我的应用程序查找数据库中不存在的id的情况。 抛出exception。 当然,对于任何Web开发人员来说,这都是一个非常标准的情况。

感谢这个答案,我知道使用救援处理的情况非常整齐,如下:

def show @customer = Customer.find(params[:id]) rescue ActiveRecord::RecordNotFound #customer with that id cannot be found redirect_to action: :index #redirect to index page takes place instead of crashing end 

如果找不到客户,则用户被重定向到索引页面。 这绝对没问题。

现在,这一切都很好,但我需要在show,edit,destroy等操作中进行相同的救援尝试,即每个需要特定id的控制器方法。

话虽如此, 这是我的问题:没有任何方法可以告诉我的控制器,如果它无法在任何方法中找到id,它将重定向到索引页面(或者,通常,执行特定的任务)?

您必须使用rescue_from执行此任务。 请参阅“ 操作控制器概述指南”中的示例

 class ApplicationController < ActionController::Base rescue_from ActiveRecord::RecordNotFound, :with => :record_not_found private def record_not_found redirect_to action: :index end end 

Rails有一个内置的rescue_from类方法:

 class CustomersController < ApplicationController rescue_from ActiveRecord::RecordNotFound, with: :index ... end 

如果您正在谈论在单个控制器中执行此操作(而不是在每个控制器中全局执行此操作),那么这里有两个选项:

您可以使用before_filter来设置资源:

 class CustomerController < ApplicationController before_filter :get_customer, :only => [ :show, :update, :delete ] def show end private def get_customer @customer = ActiveRecord.find(params[:id]) rescue ActiveRecord::RecordNotFound redirect_to :action => :index end end 

或者你可以改用一种方法。 我一直在朝着这个方向前进,而不是在视图中使用实例变量,它也可以帮助您解决问题:

 class CustomerController < ApplicationController def show # Uses customer instead of @customer end private def customer @customer ||= Customer.find(params[:id]) rescue ActiveRecord::RecordNotFound redirect_to :action => :index end helper_method :customer end 

在某些情况下,我建议您使用Model.find_by_id(id)而不是Model.find(id).find_by_id返回nil ,而不是抛出exception。 如果找不到记录。

只要确保检查nils以避免NoMethodError

PS对于它的价值, Model.find_by_id(id)在function上等同于Model.where(id: id) ,这将允许你根据需要构建一些额外的关系。