Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/64.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 未找到id时的整个控制器的一般救援-RoR_Ruby On Rails_Exception_Activerecord_Rescue - Fatal编程技术网

Ruby on rails 未找到id时的整个控制器的一般救援-RoR

Ruby on rails 未找到id时的整个控制器的一般救援-RoR,ruby-on-rails,exception,activerecord,rescue,Ruby On Rails,Exception,Activerecord,Rescue,我偶然发现了这样一种情况:我的应用程序查找数据库中不存在的id。将引发异常。当然,对于任何web开发人员来说,这都是一个相当标准的情况 多亏了我,我知道使用救援可以非常巧妙地应对这种情况,比如: def show @customer = Customer.find(params[:id]) rescue ActiveRecord::RecordNotFound #customer with that id cannot be found redirect_to action: :

我偶然发现了这样一种情况:我的应用程序查找数据库中不存在的id。将引发异常。当然,对于任何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
如果找不到客户,用户将被重定向到索引页。这绝对行得通

现在,这一切都很好,但我需要在显示、编辑、销毁等操作中进行相同的营救尝试,即每个需要特定id的控制器方法

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

Rails有一个内置的类方法:

class CustomersController < ApplicationController
  rescue_from ActiveRecord::RecordNotFound, with: :index
  ...
end
class CustomerController
您必须使用
rescue\u from
执行此任务。请参见中的示例

class ApplicationController:未找到记录
私有的
未找到def记录
将_重定向到操作::索引
结束
结束

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

只需确保检查nils以避免出现
NoMethodError


另一方面,
Model.find\u by\u id(id)
在功能上等同于
Model.where(id:id)
,这将允许您根据需要建立一些附加关系。

如果您在单个控制器中进行此操作(而不是在每个控制器中全局进行此操作)下面是几个选项:

您可以使用before_筛选器设置资源:

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[:show,:update,:delete]
def秀
结束
私有的
def get_客户
@customer=ActiveRecord.find(参数[:id])
rescue ActiveRecord::RecordNotFound
将_重定向到:action=>:index
结束
结束
或者您可以使用一种方法来代替。我一直朝着这个方向发展,而不是在视图中使用实例变量,这也将帮助您解决问题:

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
class CustomerController:index
结束
方法:客户
结束

这看起来非常优雅。我试过了,但它在浏览器中留下了一个空页面,在url中仍然显示
customers/:id
。我错过什么了吗?在我看来,它试图呈现索引,而不是重定向到索引。你说得对。。试试下面Baldrick建议的方法(例如,一个带有重定向的中间方法),“全局”一词引起了我的注意。是否有办法在所有控制器中执行此操作?这将是非常有帮助的。我认为要以全局的方式完成我所描述的可能需要一些元编程。但要在全局范围内拯救ActiveRecord::RecordNotFound,您可以在应用程序控制器中使用rescue_。太棒了,这就成功了,谢谢!出于好奇:为什么该方法应该是私有的?只是为了清洁:该方法不需要对其他控制器可见,这就是为什么它被声明为私有的原因。如果这个方法没有声明为私有,那么它也同样有效。你也可以添加一个flash消息flash[:notice]=“找不到记录”。这很好,真的帮助了我
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