rails 仅在生产中出现 nomethoderror

rails nomethoderror only in production

我有一个集成了 google 日历 API 的 rails 应用程序。应用程序部署在 heroku 上。以下代码在 localhost 中运行,但我在生产中遇到 nomethoderror,如下所示。为什么会这样?

get_own_events 的错误:

Attempting refresh of access token & retry of request
2016-02-10T13:24:34.161850+00:00 app[web.1]: 
2016-02-10T13:24:34.161853+00:00 app[web.1]: NoMethodError (undefined method `each' for nil:NilClass):
2016-02-10T13:24:34.161854+00:00 app[web.1]:   lib/google_calendar_api.rb:91:in `get_own_events'
2016-02-10T13:24:34.161855+00:00 app[web.1]:   app/controllers/events_controller.rb:18:in `index'

忙事件错误:

2016-02-10T13:24:00.716112+00:00 app[web.1]: Attempting refresh of access token & retry of request
2016-02-10T13:24:00.779120+00:00 app[web.1]: NoMethodError (undefined method `[]' for nil:NilClass):
2016-02-10T13:24:00.779121+00:00 app[web.1]:   lib/google_calendar_api.rb:38:in `get_busy_events'
2016-02-10T13:24:00.779121+00:00 app[web.1]:   app/controllers/events_controller.rb:20:in `index'

events_controller

  if params['start'] && params['end']
    @start_time = params['start'].to_datetime.rfc3339
    @end_time = params['end'].to_datetime.rfc3339
    @timezone = params['timezoneParam']
    if @user == @current_user
      @results = get_own_events(@google, @start_time, @end_time, @timezone)
    else
      @results = get_busy_events(@google, @start_time, @end_time, @timezone)
    end
  end

get_own_events方法:

def get_own_events(social_object, start_time, end_time, timezone)
  client = init_google_api_calendar_client(social_object)
  old_token = client.authorization.access_token
  service = client.discovered_api('calendar', 'v3')

  #API request/response
  result_raw = client.execute(
    :api_method => service.events.list,
    :parameters => { 'calendarId' => social_object.email,
                   'timeMin' => start_time,
                   'timeMax' => end_time,
                   'timeZone' => timezone },
    :headers => {'Content-Type' => 'application/json'})

  #token refresh if needed
  new_token = client.authorization.access_token
  if old_token != new_token
    social_object.update_attribute(:token, new_token)
    get_own_events(social_object, start_time, end_time, timezone)
  end

  #API response parsing
  result = JSON.parse(result_raw.body)['items']
  #result_timezone = JSON.parse(result_raw.body)['timeZone']

  #changing response to fullcalendar format
  formatted_event_array = []

  result.each do |event| #THIS IS LINE 91
    start_time = event['start']['dateTime'].to_datetime.rfc822
    end_time = event['end']['dateTime'].to_datetime.rfc822
    #timezone = result_timezone
    all_day = false
    title = event['summary']
    formatted_event = {}
    formatted_event['title'] = title
    formatted_event['start'] = start_time
    formatted_event['end'] = end_time
    formatted_event['allDay'] = all_day
    formatted_event_array << formatted_event
  end

  return formatted_event_array
end

get_busy_events方法:

def get_busy_events(social_object, start_time, end_time, timezone)
  client = init_google_api_calendar_client(social_object)
  old_token = client.authorization.access_token
  service = client.discovered_api('calendar', 'v3')

  #API request/response
  result_raw = client.execute(
    :api_method => service.freebusy.query,
    :body => JSON.dump({ 
            :timeMin => start_time,
            :timeMax => end_time,
            :timeZone => timezone,
            :items => [{ :id => social_object.email }]}),
    :headers => {'Content-Type' => 'application/json'})

  #token refresh if needed
  new_token = client.authorization.access_token
  if old_token != new_token
    social_object.update_attribute(:token, new_token)
    get_busy_events(social_object,start_time, end_time, timezone)
  end

  #API response parsing 
  result = JSON.parse(result_raw.body)['calendars'][social_object.email]['busy'] #THIS IS LINE 38

  #changing response to fullcalendar format
  formatted_event_array = []

  result.each do |event|
    start_time = event['start'].to_datetime.rfc822
    end_time = event['end'].to_datetime.rfc822
    formatted_event = {}
    formatted_event['title'] = 'busy'
    formatted_event['start'] = start_time
    formatted_event['end'] = end_time
    #no allDay in freebusy response, so time difference must be checked
    if event['start'].to_datetime + 1.day <= event['end'].to_datetime
      formatted_event['allDay'] = true
    else
      formatted_event['allDay'] = false
    end
    formatted_event_array << formatted_event 
  end

  return formatted_event_array
end

实际上是这样

result = JSON.parse(result_raw.body)['calendars'][social_object.email]['busy']

如果 JSON.parse(result_raw.body)['calendars'][social_object.email]['busy'] 为零,则此

result.each do |event|
# code
end

正在尝试遍历 nil。

你可以用保护条款来解决这个问题

return formatted_event_array if result.nil?
result.each do |event|
# code
end

但对我来说,这有点掩盖了裂缝。另一个错误是因为同一行。

假设 parsed_body = JSON.parse(result_raw.body)

通过链接哈希调用而不检查它会抛出错误,如果 parsed_body['calendars'] 为零或如果 parsed_body['calendars'][social_object.email] 为零

所以实际上你想检查它们是否都存在,并且 parsed_body['calendars'][social_object.email]['busy'] 存在。如果他们不这样做,那么大概 return 空数组

所以

if parsed_body['calendars'] && parsed_body['calendars'][social_object.email] && parsed_body['calendars'][social_object.email]['busy']