Rails:Model.find()或Model.find_by_id()以避免RecordNotFound

时间:2015-12-03 21:58:25

标签: ruby-on-rails find

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

一年前,我合并了三个网站,导致需要处理大量重定向。为此,我在我的应用程序控制器中创建了一个" catch all" -functionality,如下所示:

  around_filter :catch_not_found

  def catch_not_found
    yield
    rescue ActiveRecord::RecordNotFound
      require 'functions/redirections'
      handle_redirection(request.path)
  end 

另外我在routes.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 %>

这是我在我的应用程序的700多个地方使用的东西。我今天意识到的是即使找到了产品模型。调用Country.find()并找不到某些东西会导致RecordNotFound,从而导致404错误。

如果在{.find-search中找不到该国家/地区,我已经使我的应用程序符合@product.country = nil的期望。我现在知道情况并非如此 - 它会创建一个RecordNotFound。基本上,如果我加载Product#show,我将得到一个404页,我希望得到500错误(因为@product.country = nilnil.name不起作用)。

我的问题

我现在的大问题。我在我的应用程序中做错了,我应该总是将Model.find_by_id用于我的Country.find(...some id...)之类的查询吗?这里的最佳做法是什么?

或者,问题在于我在应用程序控制器中的所有问题吗?

2 个答案:

答案 0 :(得分:2)

回答你的问题:

我应该始终使用Model.find_by_id

如果您想按ID找到,请使用Country.find(...some id...)。如果你想找到别的东西,请使用eg。 Country.find_by(name: 'Australia')。 Rails 4中不再支持find_by_name语法。

但是,这不是你的问题。

或者,问题在于我在应用程序控制器中的问题吗?

是的,这对我来说听起来像是一种痛苦的食谱。我不确定你具体做了什么,或者你的重定向的性质是什么,但基于我对你所做的事情的模糊感,这里是我和我的方式。 #39; d接近它:

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

基本上,您希望列出要重定向的所有URL的大胖列表,以及要将其重定向到的位置,然后按照Web服务器的预期方式对其进行格式化,并配置您的Web服务器以执行重定向为了你。搜索eg&#34; 301重定向nginx&#34;或&#34; 301重定向apache&#34;找出有关如何设置的信息。

如果您有很多要重定向的网址,那么您可能希望使用代码生成列表(大多数逻辑应该已经存在于您的handle_redirection(request.path)方法中)。< / p>

一旦您运行了该代码并生成了该列表,您就可以抛弃该代码,您的网络服务器将处理旧网站的重定向,并且您的rails应用程序可以愉快地继续,而不知道以前的站点/ URL,并且应用程序控制器中没有危险的catch-all逻辑。

答案 1 :(得分:1)

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

在Rails中,您使用rescue_from来处理控制器层上的异常:

class ApplicationController < ActionController::Base

  rescue_from SomeError, with: :oh_noes

  private def oh_noes
    render text: 'Oh no.'
  end
end

然而,Rails已经通过提供静态html页面来处理一些异常(其中包括ActiveRecord::RecordNotFound)。你可以override with dynamic handlers

然而,@ joshua.paling已经指出你应该在服务器级而不是你的应用程序中处理重定向。