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