ruby-on-rails 接收非nil类的nil:NilClass错误

wgmfuz8q  于 2023-05-02  发布在  Ruby
关注(0)|答案(1)|浏览(183)

下面是让我抓狂的代码:

puts document.nil?  # print False

  if document.nil?  # shouldn't enter since document.nil? is false
    begin
      document = conect_documents.find("123")
    rescue ActiveRecord::RecordNotFound => e
      return false
    end
  end

  attrs = document.attributes.key?('import')  # thows  undefined method `attributes' for nil:NilClass

我错过了什么
编辑:完整堆栈跟踪

NoMethodError:
   undefined method `attributes' for nil:NilClass
 # ./path/permission.rb:217:in `edit?'
 # ./path/documents_controller.rb:67:in `update'
 # ./spec/login_spec_helper.rb:11:in `block in process'
 # ./spec/login_spec_helper.rb:32:in `catch'
 # ./spec/login_spec_helper.rb:32:in `_catch_warden'
 # ./spec/login_spec_helper.rb:11:in `process'
 # ./path/documents_controller_spec.rb:468:in `block (5 levels) in <top (required)>'
zpjtge22

zpjtge221#

简化代码记录和传播异常

你在最初的问题中没有提供一个可重复的例子。但是,您似乎对实际控制流的工作方式和所涉及的对象做了许多假设,这些假设可能并不正确。这些假设包括但可能不限于:
1.#nil表示“非空”
1.调用#conect_documents(“connect”中的第二个n在哪里?)从不返回nil或空对象
1.documents 总是包含一个可以#respond_to的对象。(:attributes)

  1. documents.attributes总是返回一个可以#respond_to?(:key?)
    1.您正在拯救正确的异常
    1.你在一个你可以从return
    从您发布的示例中,这些事情都不能证明是真的,堆栈跟踪清楚地显示conect_documents(可能是输入错误)返回nil或另一个没有#attributes方法的对象,这就是它引发异常的原因。
    下面的示例可能对您的应用程序不完全有效,但将说明如何使用临时变量并断开较长的方法链,以更有效地调试此应用程序,并检查您可能没有正确检查的其他异常。
# let errors get raised rather than peppering safe
# navigators or if/thens so you can figure out what's
# actually wrong
def foo document=nil
  document = connect_documents.find(123) if document.blank?
  attrs = document.attributes
  attrs.key? "import"

# this is all you need to handle missing IDs;
# don't capture the exception object if you
# have no use for it
rescue ActiveRecord::RecordNotFound
  false

# rescue other exceptions for debugging, then re-raise
rescue => e
  # find out what's really being raised; use $stderr.puts if
  # you're not using the Rails logger for some unknown reason
  logger.error "debugging exception #{e.class}: #{e.message}"

  # document may be nil, empty, or not respond to #attributes;
  # find out what the document object actually is
  logger.debug "document: #{document.inspect}"

  # re-raise the original exception
  raise e
end

一旦隔离了bug,就可以删除第二个救援子句。但是,您可能仍然希望重构,以便在Document模型中进行验证,而不是将DocumentController方法与难以调试的东西混淆在一起。

相关问题