关系随机引发ActiveRecord::RecordNotFound



在尝试获取特定用户的订单记录时,偶尔会引发ActiveRecord::RecordNotFound

这里有一些需要注意的地方。

  • 访问/orders/:id时会引发此错误,但并非所有用户都会出现此错误。我们跟踪已完成的订单(意味着你最终会出现在订单页面上(,大约50%的人会得到404分。请注意,我们谈论的是50%的用户,而不是请求。如果它为特定用户的订单显示404一次,它将始终显示404
  • 该记录的存在是因为它可以通过控制台使用记录在控制器中的相同数据进行访问
  • 重新部署应用程序时,问题消失

可能是什么问题?

我正在运行4.2.0轨道。

class OrdersController < ApplicationController
  #
  # GET /orders/:id
  #
  def show
    Rails.logger.info "current_user=#{current_user.id}, params[:id]=#{params[:id]}"
    @order = current_user.orders.find(params[:id])
  end
end

class ApplicationController < ActionController::Base
  def current_user
    @_current_user ||= User.find_by_id(cookies.signed[:uid])
  end
end
class User < ActiveRecord::Base
  has_many :subscriptions
  has_many :orders, through: :subscriptions
end
class Order < ActiveRecord::Base
  has_one :user, through: :subscription
end
class Subscription < ActiveRecord::Base
  belongs_to :user
end

这是日志输出

[User#id=2454266]   Parameters: {"id"=>"1553"}
[User#id=2454266] current_user=2454266, params[:id]=1553 <==== Rails.logger.info
[User#id=2454266] Completed 404 Not Found in 240ms
[User#id=2454266]
ActiveRecord::RecordNotFound (Couldn't find Order with 'id'=1553):
  app/controllers/orders_controller.rb:6:in `show'

在控制台中运行User.find(2454266).orders.find(1553)是有效的。

还要注意,可以跳过关系,直接进入订单模型,如

class OrdersController < ApplicationController
  #
  # GET /orders/:id
  #
  def show
    @order = Order.find(params[:id])
  end
end

我们得出结论的方式可以通过查看注释列表找到。

我们的调查结果总结如下:

  1. 订单已缓存,或者current_user已过期(以及缓存的关联(
  2. 直接进入订单工作(即order.find/User.find(current_User.id(.orders

我们得出的解决方案是:

current_user.reload!

在执行之前

current_user.orders.find(params[:id])
class ApplicationController < ActionController::Base
  def current_user
    @_current_user ||= User.find_by_id(cookies.signed[:uid])
  end
  def user_signed_in?
    @_current_user.present?
  end
end
class OrdersController < ApplicationController
 def show
   if user_signed_in?
     @order = current_user.orders.find(params[:id])
   else
    return redirect_to <404 page or any>, alert: 'Order not found'
   end
 end
end

我认为你必须首先检查用户的存在,然后你才能追踪错误

当我遇到问题时,我通常会使用这种方法

def show
  if user_signed_in?
    begin
      @order = current_user.orders.find(params[:id])
    rescue => e
      binding.pry
    end
  else
   return redirect_to <404 page or any>, alert: 'Order not found'
  end
end

但是你需要"rails prick"gem,优点是rails会在出现异常时启动rails控制台

最新更新