简体   繁体   English

NoMethodError:未定义的方法“+”用于 nil:NilClass 用于私有方法中的变量

[英]NoMethodError: undefined method `+' for nil:NilClass for variable in private method

Hi I have a service class which is pulling information from Hubspot.嗨,我有一项服务 class 正在从 Hubspot 提取信息。

module HubspotApi
  class CompanyImporter < ApplicationService
    MAX_RETRIES = 3

    def initialize(company_vid)
      @company_vid = company_vid
      @attempt = 0
    end

    def service_body
      imported_profile
    end

    private
 
    attr_reader :company_vid, :attempt

    def imported_profile
      ## load hubspot record over here and take other actions
    end

    def hubspot_record
      @hubspot_record ||= Hubspot::Company.find_by_id(company_vid.to_i)
    rescue Hubspot::RequestError
      if (attempt += 1) <= MAX_RETRIES
        sleep 2**attempt
        retry
      else
        @messages << 'Raise some hubspot error'
      end
    end
  end
end

I tried calling this with an incorrect company_vid to make sure the retry works properly and I keep getting the error:我尝试使用不正确的company_vid调用它以确保重试正常工作,但我不断收到错误消息:

NoMethodError: undefined method `+' for nil:NilClass from `rescue in hubspot_record'
Caused by Hubspot::RequestError: Response body: {"status":"error","message":"resource not found"}

I am not sure if I am having a brain-fart here but I just cannot figure out the error here since the variable should be defined我不确定我是否在这里放屁,但我只是无法弄清楚这里的错误,因为应该定义变量

In Ruby, local variables are defined from the moment that an assignment to them is parsed (NOT executed).在 Ruby 中,局部变量从对它们的赋值被解析(不执行)的那一刻起定义。

Since you are assigning to attempt , Ruby will make attempt a local variable of hubspot_record .由于您分配给attempt ,因此 Ruby 将attempt使用hubspot_record的局部变量。 However, since it is not initialized, it will evaluate to nil .但是,由于它没有被初始化,它将评估为nil

attempt += 1

is equivalent to相当于

attempt = attempt + 1

And since attempt is un-initialized and evaluates to nil , this is essentially evaluating nil + 1 .并且由于attempt未初始化并评估为nil ,这本质上是评估nil + 1

If you want to use the attribute reader method, you have to make it clear to Ruby that you are intending a message send and not access a local variable.如果要使用属性读取器方法,则必须向 Ruby 说明您打算发送消息而不是访问局部变量。 There are two ways to do this: a local variable cannot have a receiver and a local variable cannot have an argument list.有两种方法可以做到这一点:局部变量不能有接收者,局部变量不能有参数列表。 So, if you add either one of those, Ruby will know it is a message send and not a local variable:因此,如果您添加其中任何一个,Ruby 将知道它是消息发送而不是局部变量:

attempt()
self.attempt

Either one of those will make it clear to Ruby that you intend to call the HubspotApi::CompanyImporter#attempt method.其中任何一个都会让 Ruby 清楚您打算调用HubspotApi::CompanyImporter#attempt方法。

However, that still will not work, because you are trying to assign to and you don't actually have an attribute writer, so your next error message is going to be something like但是,这仍然行不通,因为您正在尝试分配给并且您实际上没有属性编写器,因此您的下一条错误消息将类似于

NoMethodError: undefined method `attempt=' for HubspotApi::CompanyImporter

The way to fix this problem pre-Ruby 2.7 is to:在 Ruby 2.7 之前解决这个问题的方法是:

change attr_reader:attempt to attr_accessor:attemptattr_reader:attempt更改为attr_accessor:attempt

And

def hubspot_record
  @hubspot_record ||= Hubspot::Company.find_by_id(company_vid.to_i)
rescue Hubspot::RequestError
  if (self.attempt = attempt + 1) <= MAX_RETRIES ## This was fixed in Ruby 2.7 but for earlier versions you need to read using self and write directly.
    sleep 2**attempt
    retry
  else
    @messages << 'Raise some hubspot error'
  end
end

Link for update in Ruby 2.7: https://blog.saeloun.com/2019/12/24/ruby-2-7-allows-calling-a-private-method-with-self.html Ruby 2.7 中的更新链接: https://blog.saeloun.com/2019/12/24/ruby-2-7-allows-calling-a-private-method-with-self.Z5E056FDC70D8226C

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM