关系随机引发ActiveRecord :: RecordNotFound

时间:2015-09-22 14:16:56

标签: ruby-on-rails ruby activerecord

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

这里有一些注意事项。

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

问题是什么?

我正在运行rails 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

2 个答案:

答案 0 :(得分:1)

通过浏览评论列表可以找到我们得出结论的方式。

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

  1. 任何订单都被缓存,或者current_user已过时(以及缓存的关联)
  2. 直接订购作品(即Order.find / User.find(current_user.id).orders ...
  3. 我们到达的解决方案是:

    current_user.reload!
    

    在执行

    之前
    current_user.orders.find(params[:id])
    

答案 1 :(得分:-1)

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-pry'宝石,优点是当有异常时rails会启动rails控制台