Connect Rails App with google drive api

google_drive.png

In this article, I'll show you how to access to google drive api using using the OAuth 2.0 and redis storage.

Prerequisites

For this article, you'll need:

  • Access to the internet and a web browser.
  • A Google account with Google Drive enabled.
  • redis for store token
  • rails

1. Prepare your project

First you’ll need to sign in to the Google Developers Console and register your app:

  • create rails project. For the demo I am going to use our previous project PlantLover, so when you follow this article, but it has problem please check my previous articlesIntergrate Redis on Rails.
  • create a new project, and enabling the Google API you want to use (this case drive) on the “APIs” page.
  • Set the name of your application and your support email address on the “OAuth consent screen” page.
  • Create a new client on the “Credentials” page. Choose “Web application” as the application type (it should be selected by default), and edit the “Authorized redirect URIs” list to make sure the callback URL you’ll be using in development is included. This is the URL in your application that Google will redirect back to, e.g. http://localhost:3000/oauth2callback.
  • Click the (Download JSON) button to the right of the client ID.
  • Move the download file into plantlover/lib/google_drive and re name to client_secret.json

2. Install google-api-client gem

gem 'google-api-client'

Then run bundle. The gem may come with a lot of its dependencies which help you to work with google API.

3. Create class for working with drive google api

Let create file name google_drive.rb in plantlover/lib/google_drive.

require 'google/apis/drive_v2'
require 'google/api_client/client_secrets'

require 'googleauth'
require 'googleauth/stores/redis_token_store'

class MyDrive
  OOB_URI = "localhost:3000/oauth2callback"
  attr_writer :authorizer, :drive, :redirect_uri, :credentials

  def initialize
    client_id = Google::Auth::ClientId.from_file("#{Rails.root}/lib/google_drive/client_secret_1.json")
    scope = ['https://www.googleapis.com/auth/drive']
    token_store = Google::Auth::Stores::RedisTokenStore.new(redis: $redis)
    @authorizer = Google::Auth::UserAuthorizer.new(
    client_id, scope, token_store)
    user_id = 'darazone'
    @credentials = @authorizer.get_credentials(user_id)
    @drive = Google::Apis::DriveV2::DriveService.new
    @drive.authorization = @credentials
  end

  def authorization_url
    @authorizer.get_authorization_url(base_url: OOB_URI)
  end

  def get_credentials
    @credentials
  end

  def set_authorization
    @drive.authorization = @credentials
  end

  def get_drive
    @drive
  end
  def save_credentials(code)
    user_id = 'darazone'
    @credentials = @authorizer.get_and_store_credentials_from_code(
      user_id: user_id, code: code, base_url: OOB_URI)
    @drive.authorization = @credentials
  end

  def list_files(options = {})
    @drive.list_files(options: options)
  end

  def upload(file, options = {})
    # file[:parent_ids] = [{id: 'id'}]
    file_obj = Google::Apis::DriveV2::File.new({
      title: file[:title],
      parents: file[:parent_ids]
    })
    f = @drive.insert_file(file_obj, upload_source: file[:path])
    f.id
  rescue
    nil
  end

  def delete(id, options = {})
    @drive.delete_file(id)
  end

  def update(id, file, options = {})
    @drive.patch_file(id, file)
  end

  def get(id, options = {})
    @drive.get_file(id)
  end

  def list_children_files(parent_id, options = {})
    @drive.list_children(parent_id, options: options).items
  end
end

Let’s go through to some methods:

  • initialize: use init object for connect to google api such as client_secret, client_id, redirect_url. And storage for store the google token code after we get authorize.
  • authorization_url for generate url to obtain access code.
  • save_credentials(code) for save the credentials after we get code from google.
  • other methods which we use to work with drive.

4. Config with our rails project

Add require "#{config.root}/lib/google_drive/google_drive.rb" in config/applicaltion.rb

Create init file in config/initialize name drive.rb and add one line of code:

$drive = MyDrive.new

Here we can access $drive from everywhere in our project.

Add action for respond callback in route: config/routes.rb

....
get 'oauth2callback' => 'static_pages#set_google_drive_token'
....

In application controller add:

before_filter :google_login, except: [:set_google_drive_token]

def google_login
  unless $drive.get_credentials
    redirect_to('/oauth2callback')
  end
end

And in static_page controller add:

class StaticPagesController < ApplicationController
  def set_google_drive_token
    if request['code'] == nil
      redirect_to($drive.authorization_url)
    else
      $drive.save_credentials(request['code'])
      redirect_to('/')
    end
  end
end

5. Let's try

Add root path: config/routes.rb

....
root 'static_pages#home'
....

Add action home in static_page controller.

class StaticPagesController < ApplicationController
  render json: { list_files: $drive.list_files }
end

Than run your server:

Screen Shot 2016-07-24 at 11.49.27 PM.png

Ya, it works.

resource

What's next

The next step, I am going to show you how we intergrate google drive with carrierwave. So we can store our file 15G freely. Stay tune.


All Rights Reserved