无法通过救援捕获ActiveRecord :: RecordNotFound

时间:2022-09-11 17:36:03

I'm new to Ruby, please bear with me if this is a stupid question, or if I'm not following the best practice.

我是Ruby的新手,如果这是一个愚蠢的问题,或者如果我没有遵循最佳实践,请耐心等待。

I'm finding an object in the DB using find(), and expect it to throw RecordNotFound in case the object of the id does not exist, like this.

我在使用find()在DB中找到一个对象,并期望它抛出RecordNotFound,以防id的对象不存在,就像这样。

  begin
    event = Event.find(event_id)
  rescue ActiveRecord::RecordNotFound => e
    Rails.logger.debug "Event does not exist, id: " + event_id
    return {
        # return "unauthorized" to avoid testing existence of event id
        # (some redacted codes)
    }
  end 

But somehow it is not caught (the log in the rescue block is not printed) and the entire program just return internal server error. Here's the stack trace:

但不知怎的,它没有被捕获(救援块中的日志没有打印),整个程序只返回内部服务器错误。这是堆栈跟踪:

Completed 500 Internal Server Error in 22ms (ActiveRecord: 1.0ms)



ActiveRecord::RecordNotFound (Couldn't find Event with 'id'=999):

lib/sync/create_update_event_handler.rb:78:in `handleRequest'
app/controllers/sync_controller.rb:36:in `block in sync'
app/controllers/sync_controller.rb:31:in `each'
app/controllers/sync_controller.rb:31:in `sync'
  Rendering /usr/local/rvm/gems/ruby-2.4.0/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout
  Rendering /usr/local/rvm/gems/ruby-2.4.0/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/_source.html.erb
  Rendered /usr/local/rvm/gems/ruby-2.4.0/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/_source.html.erb (6.4ms)
  Rendering /usr/local/rvm/gems/ruby-2.4.0/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb
  Rendered /usr/local/rvm/gems/ruby-2.4.0/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (2.3ms)
  Rendering /usr/local/rvm/gems/ruby-2.4.0/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb
  Rendered /usr/local/rvm/gems/ruby-2.4.0/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (1.9ms)
  Rendered /usr/local/rvm/gems/ruby-2.4.0/gems/actionpack-5.0.6/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout (36.6ms)

The only thing I can think of is there are two different ActiveRecord::RecordNotFound, and I'm catching the wrong one, but I don't know if it is the case or how I can verify it. What did I do wrong?

我唯一能想到的是有两个不同的ActiveRecord :: RecordNotFound,我抓错了,但我不知道是否是这种情况或我如何验证它。我做错了什么?

======================================

Update

The problem is in the rescue block, I was concatenating event_id (an integer) to a string. The RecordNotFound exception was indeed caught, but when the type error was thrown in the rescue block, the wrong error message was printed.

问题在于救援块,我将event_id(一个整数)连接到一个字符串。确实捕获了RecordNotFound异常,但是当在rescue块中抛出类型错误时,打印出错误的错误消息。

3 个解决方案

#1


1  

Turned out the error message is wrong.

原来错误信息是错误的。

The problem is that I was concentating the event_id (an integer) to a string. But somehow Rails prints out the RecordNotFound exception.

问题是我将event_id(一个整数)集中到一个字符串。但不知何故Rails打印出RecordNotFound异常。

The problem is fixed by replacing Rails.logger.debug "Event does not exist, id: " + event_id with Rails.logger.debug "Event does not exist, id: " + event_id.to_s

通过替换Rails.logger.debug“事件不存在,id:”+ event_id与Rails.logger.debug修复问题“事件不存在,id:”+ event_id.to_s

Thanks @lacostenycoder for bringing my attention to the error message.

感谢@lacostenycoder将我的注意力集中在错误消息上。

#2


1  

You won't get an error if you do

如果你这样做,你不会得到错误

event = Event.find_by(id: event_id)

event = Event.find_by(id:event_id)

In this case if the record can't be found by ID it will just event == nil be nil. In this case if the record can't be found by ID it will just event == nil be nil.

在这种情况下,如果ID无法找到记录,那么事件== nil为nil。在这种情况下,如果ID无法找到记录,那么事件== nil为nil。

The code you pasted works fine for me. If you don't see output in the log, check your environment and log level settings INFO, WARN, DEBUG etc. 500 error indicates some kind of controller action raising the error.

你粘贴的代码对我来说很好。如果您没有在日志中看到输出,请检查您的环境和日志级别设置INFO,WARN,DEBUG等.500错误表示某种控制器操作引发错误。

see Set logging levels in Ruby on Rails

请参阅在Ruby on Rails中设置日志记录级别

To be sure your rescue block is executing try doing something besides log. If you're running a development server you can try :

为了确保您的救援块正在执行,请尝试执行除日志之外的操作。如果您正在运行开发服务器,可以尝试:

    begin
         event = Event.find(event_id)
     rescue ActiveRecord::RecordNotFound => e
         msg = "Event does not exist, id: #{event_id.to_s}"
         Rails.logger.debug msg.
         puts msg 
         binding.pry # if you have gem 'pry' in your development gems.
         File.open('test.log', 'w') {|f| f.write msg} #check if this appears in root of your app
         return {
                 # return "unauthorized" to avoid testing existence of event id
                 # (some redacted codes)
         }
     end 

UPDATE: I changed the string interpolation according to your answer. You can also call .to_s inside interpolation instead of closing quotes and appending.

更新:我根据你的答案改变了字符串插值。你也可以在插值中调用.to_s而不是关闭引号和追加。

#3


0  

@event = Event.find(params[:id]). you should write instead params[:id] .That's the cause of an error.

@event = Event.find(params [:id])。你应该写params [:id]。这就是错误的原因。

#1


1  

Turned out the error message is wrong.

原来错误信息是错误的。

The problem is that I was concentating the event_id (an integer) to a string. But somehow Rails prints out the RecordNotFound exception.

问题是我将event_id(一个整数)集中到一个字符串。但不知何故Rails打印出RecordNotFound异常。

The problem is fixed by replacing Rails.logger.debug "Event does not exist, id: " + event_id with Rails.logger.debug "Event does not exist, id: " + event_id.to_s

通过替换Rails.logger.debug“事件不存在,id:”+ event_id与Rails.logger.debug修复问题“事件不存在,id:”+ event_id.to_s

Thanks @lacostenycoder for bringing my attention to the error message.

感谢@lacostenycoder将我的注意力集中在错误消息上。

#2


1  

You won't get an error if you do

如果你这样做,你不会得到错误

event = Event.find_by(id: event_id)

event = Event.find_by(id:event_id)

In this case if the record can't be found by ID it will just event == nil be nil. In this case if the record can't be found by ID it will just event == nil be nil.

在这种情况下,如果ID无法找到记录,那么事件== nil为nil。在这种情况下,如果ID无法找到记录,那么事件== nil为nil。

The code you pasted works fine for me. If you don't see output in the log, check your environment and log level settings INFO, WARN, DEBUG etc. 500 error indicates some kind of controller action raising the error.

你粘贴的代码对我来说很好。如果您没有在日志中看到输出,请检查您的环境和日志级别设置INFO,WARN,DEBUG等.500错误表示某种控制器操作引发错误。

see Set logging levels in Ruby on Rails

请参阅在Ruby on Rails中设置日志记录级别

To be sure your rescue block is executing try doing something besides log. If you're running a development server you can try :

为了确保您的救援块正在执行,请尝试执行除日志之外的操作。如果您正在运行开发服务器,可以尝试:

    begin
         event = Event.find(event_id)
     rescue ActiveRecord::RecordNotFound => e
         msg = "Event does not exist, id: #{event_id.to_s}"
         Rails.logger.debug msg.
         puts msg 
         binding.pry # if you have gem 'pry' in your development gems.
         File.open('test.log', 'w') {|f| f.write msg} #check if this appears in root of your app
         return {
                 # return "unauthorized" to avoid testing existence of event id
                 # (some redacted codes)
         }
     end 

UPDATE: I changed the string interpolation according to your answer. You can also call .to_s inside interpolation instead of closing quotes and appending.

更新:我根据你的答案改变了字符串插值。你也可以在插值中调用.to_s而不是关闭引号和追加。

#3


0  

@event = Event.find(params[:id]). you should write instead params[:id] .That's the cause of an error.

@event = Event.find(params [:id])。你应该写params [:id]。这就是错误的原因。