Ruby on rails Rails:Model.find()或Model.find\u by_id()避免RecordNotFound

Ruby on rails Rails:Model.find()或Model.find\u by_id()避免RecordNotFound,ruby-on-rails,find,Ruby On Rails,Find,我刚刚意识到我的网站上有一个很难找到的bug。我经常使用Model.find从数据库中检索数据 一年前,我合并了三个网站,导致了许多需要处理的重定向。为此,我在我的应用程序控制器中创建了“全面覆盖”功能,如下所示: around_filter :catch_not_found def catch_not_found yield rescue ActiveRecord::RecordNotFound require 'functions/redirection

我刚刚意识到我的网站上有一个很难找到的bug。我经常使用Model.find从数据库中检索数据

一年前,我合并了三个网站,导致了许多需要处理的重定向。为此,我在我的应用程序控制器中创建了“全面覆盖”功能,如下所示:

  around_filter :catch_not_found

  def catch_not_found
    yield
    rescue ActiveRecord::RecordNotFound
      require 'functions/redirections'
      handle_redirection(request.path)
  end 
此外,我在我的
路线的底部有这个。rb

  match '*not_found_path', :to => 'redirections#not_found_catcher', via: :get, as: :redirect_catcher, :constraints => lambda{|req| req.path !~ /\.(png|gif|jpg|txt|js|css)$/ }
重定向控制器具有:

  def not_found_catcher
    handle_redirection(request.path)   
  end
我不确定这些事情是否与这个问题有关,但我想最好还是说出来

我的实际问题

我经常使用Model.find从数据库中检索数据。假设我有一个控制器的产品模型,如下所示:

def show
@product = Product.find(params[:id])
@product.country = Country.find(...some id that does not exist...)
end

# View
<%= @product.country.name %>
def显示
@product=product.find(参数[:id])
@product.country=country.find(…一些不存在的id…)
结束
#看法
这是我在应用程序中700多个地方使用的东西。我今天意识到的是,即使可以找到产品模型。调用Country.find()而不查找某个内容会导致RecordNotFound,这反过来会导致404错误

我的应用程序是基于这样一个期望而开发的:如果在.find搜索中找不到该国家,则
@product.country=nil
。我现在知道情况并非如此——它将创建一个RecordNotFound。基本上,如果我加载产品#show,我将得到一个404页面,预计会出现500个错误(因为
@Product.country=nil
nil.name
不起作用)

我的问题

我现在的大问题。我的应用程序是否做错了,我是否应该始终使用Model.find_by_id来查询我的
国家/地区。find(…某些id…)
?这里最好的做法是什么


或者,问题是否在应用程序控制器中的“一网打尽”中?

回答您的问题:

我是否应该始终使用Model.find by_id

如果要按id查找,请使用
Country.find(…某些id…)
。如果你想找到其他的东西,使用例如
Country.find_by(name:'Australia')
。Rails 4不再支持
find_by_name
语法

但这只是个旁白,不是你的问题

或者,问题是否存在于应用程序控制器的“一网打尽”中?

是的,对我来说,这听起来像是一种止痛药。我不确定你具体在做什么,也不确定你的重定向是什么性质的,但基于我对你试图做什么的模糊感觉,以下是我的做法:

您的Rails应用程序不应负责从以前的网站/应用程序重定向路由。这应该是您的web服务器的责任(例如nginx或apache或其他)

基本上,您希望创建一个包含所有要重定向的URL的大列表,以及重定向到的位置,然后按照Web服务器期望的方式对其进行格式化,并配置Web服务器为您执行重定向。搜索例如“301重定向nginx”或“301重定向apache”,以了解有关如何设置的信息

如果您有很多URL要重定向,您可能需要生成带有代码的列表(大多数逻辑应该已经存在于
handle\u重定向(request.path)
方法中)


一旦您运行了该代码并生成了列表,您就可以扔掉该代码,您的Web服务器将处理来自旧站点的重定向,您的rails应用程序可以愉快地继续运行,而不需要知道以前的站点/URL,也不需要在您的应用程序控制器中使用危险的“一网打尽”逻辑。

回答您的问题:

我是否应该始终使用Model.find by_id

如果要按id查找,请使用
Country.find(…某些id…)
。如果你想找到其他的东西,使用例如
Country.find_by(name:'Australia')
。Rails 4不再支持
find_by_name
语法

但这只是个旁白,不是你的问题

或者,问题是否存在于应用程序控制器的“一网打尽”中?

是的,对我来说,这听起来像是一种止痛药。我不确定你具体在做什么,也不确定你的重定向是什么性质的,但基于我对你试图做什么的模糊感觉,以下是我的做法:

您的Rails应用程序不应负责从以前的网站/应用程序重定向路由。这应该是您的web服务器的责任(例如nginx或apache或其他)

基本上,您希望创建一个包含所有要重定向的URL的大列表,以及重定向到的位置,然后按照Web服务器期望的方式对其进行格式化,并配置Web服务器为您执行重定向。搜索例如“301重定向nginx”或“301重定向apache”,以了解有关如何设置的信息

如果您有很多URL要重定向,您可能需要生成带有代码的列表(大多数逻辑应该已经存在于
handle\u重定向(request.path)
方法中)

一旦您运行了该代码并生成了列表,您就可以扔掉该代码,您的Web服务器将处理来自旧站点的重定向,您的rails应用程序可以在不知道以前的站点/URL的情况下继续运行,并且在应用程序控制器中没有危险的“一网打尽”逻辑。

这是处理异常的一种非常有趣的方法

在用于处理控制器层上异常的Rails中:

class ApplicationController < ActionController::Base

  rescue_from SomeError, with: :oh_noes

  private def oh_noes
    render text: 'Oh no.'
  end
end
class ApplicationController
然而,Rails已经通过提供静态html页面来处理一些异常(其中包括
ActiveRecord::RecordNotFound
)。你可以

然而,正如@joshua.paling已经指出的,您应该在服务器级别inst上处理重定向