How to access your Google Drive files with Ruby

I use Google Drive excessively for documents and spreadsheets, and recently I created a IFTT recipe to store all attachments I receive to my Google Mail email address on Google Drive. No more downloading from Gmail, looking for the downloaded file, opening Google Drive, uploading etc., everything is right there in its own folder. (funnily enough, Gmail added the possibility to open documents right in Google Drive shortly thereafter).

Now, a couple of days ago I had to access some files on my Google Drive from a Rails app, and after some trial and error I found a easy way to do so, which I want to detail in this post.

First, you need to enable the Drive API for your account.

Then you need the google-api-client gem, any version >= 0.7.0 will do. This gem uses Signet for OAuth, but in the latest version of Signet there is a small bug which I have submitted a pull request for but that hasn't been accepted yet at the time of writing. So my recommendation is to check whether a version of Signet has been released that includes my PR or use my fork of that gem for now:

gem 'signet', github: 'krautcomputing/signet', branch: 'token_credential_uri_as_hash'
gem 'google-api-client', '>= 0.7.0'

Update September 25 2015: My pull request for Signet has long been accepted, so you can remove the first line from the code above (simply make sure you're using Signet version >= 0.5.1)

Alright, here is the complete code (for my specific use-case) to access Google Drive:

require 'google/api_client'
require 'google/api_client/auth/file_storage'
require 'google/api_client/auth/installed_app'

class GoogleDrive
  CREDENTIALS_FILE = Rails.root.join('tmp', 'google_api_credentials.json')

  def initialize
    credentials_storage =
    @client =
      application_name:    'MyApp',
      application_version: '1.0.0'
    @client.authorization = credentials_storage.authorization || begin
      installed_app_flow =
        client_id:     ENV['GOOGLE_API_CLIENT_ID'],
        client_secret: ENV['GOOGLE_API_CLIENT_SECRET'],
        scope:         ENV['GOOGLE_API_SCOPE']
    @drive = @client.discovered_api('drive', 'v2')

  def download_latest_proxylist(search_period = 1.week.ago)
    modified_date = search_period.strftime('%Y-%m-%dT%H:%M:%S%z')
    result = @client.execute(
      api_method: @drive.files.list,
      parameters: {
        q: %(title contains "proxylist" and modifiedDate > "#{modified_date}")
    file =['items'].first
    download_url = file['downloadUrl']
    result = @client.execute(uri: download_url)
    output_file = Rails.root.join('tmp', file['originalFilename'])
    IO.binwrite output_file, result.body

Google uses OAuth authorization for its API and the easiest way to access the API from the command line is to use Google::APIClient::InstalledAppFlow (source).

The first time you run this, a browser window will open and you have to greant access to Google Drive to your app ("MyApp" in this example). Then the authorization credentials will be saved in tmp/google_api_credentials.json in your Rails app and those will be used in all subsequent calls. Delete that file to redo the browser authorization.

So the initialize method sets up the API client for the Google Drive API and the download_latest_proxylist method uses that API to download a file. It looks for, as you might have guessed, a file containing a proxy list by using the drive.files.list method with some search parameters (title of the file must contain "proxylist" and it must have been modified in the last week.) I grab the first result of that search and download it. Remember to use IO.binwrite instead of IO.write for binary files.

And that's pretty much it, you can read more about it in the source code of the google-api-ruby-client gem or in the docs:

Discuss this post on Hacker News

Ideas? Constructive criticism? Think I'm stupid? Let me know in the comments!