def method_missing(method, *args)
      api_method = map[method.to_s]
      args = args.last.is_a?(Hash) ? args.last : {} # basically #extract_options!
      methods_or_resources = api_method['methods'] || api_method['resources']
      if methods_or_resources
        API.new(access_token, api, methods_or_resources)
      else
        url, options = build_url(api_method, args)

        raise ArgumentError, ":body parameter was not passed" if !options[:body] && %w(POST PUT PATCH).include?(api_method['httpMethod'])

        send(api_method['mediaUpload'] && args[:media] ? :upload : :request, api_method['httpMethod'].downcase, url, options)
      end
    end
def method_missing(method, *args)
      api_method = map[method.to_s]
      args = args.last.is_a?(Hash) ? args.last : {} # basically #extract_options!
      methods_or_resources = api_method['methods'] || api_method['resources']
      if methods_or_resources
        API.new(access_token, api, methods_or_resources)
      else
        url, options = build_url(api_method, args)

        raise ArgumentError, ":body parameter was not passed" if !options[:body] && %w(POST PUT PATCH).include?(api_method['httpMethod'])

        send(api_method['mediaUpload'] && args[:media] ? :upload : :request, api_method['httpMethod'].downcase, url, options)
      end
    end
Taking over #method_missing here allows us to chain multiple methods onto a API
 instance. If the current place we are in the API includes this method, then let's call it!
 If not, and there are multiple methods below this section of the API, build a new API
 and do it all over again.

 As an example:

   User.find(1).google.drive.files.list => we will be calling this method twice, once to find all
   methods within the files section of the API, and once to send a request to the #list API method,
   delegating to the #request method above.

   User.find(1).google.drive.files.permissions.list => we will end up calling this method three times,
   until we get to the end of the chain.
   (Note: This method chain doesn't map to an actual Google Drive API method.)

 If the API method includes a mediaUpload key, we know that this method allows uploads, like to upload
 a new Google Drive file. If so, we call the #upload method instead of #request.