Google Spreadsheet へ Ruby を使ってアクセスする(OAuth)

Google SpreadsheetのセルをRubyで参照したり、セルに書き込む方法をメモします。

認証は OAuth を使います。Googleの id, password を使って認証する方法がググると見つかりますが、この方法は現在は非推奨となっていて、代わりに OAuth を使うことが推奨されています。

今回は以下の2個のgemを組み合わせて使いました。

* [google_drive](https://rubygems.org/gems/google_drive) 認証部分
* [google-drive-ruby](https://github.com/gimite/google-drive-ruby) spreadsheet関連の操作


# 準備

1. Developers Console にログインし、プロジェクトを作成する
2. API -> Drive API を有効にする
3. クライアントIDを作成する
  1. アプリケーションの種類は Installed application を選択する
  1. タイプは **その他** を選択
4. 作成したクライアントIDのページにある **JSONをダウンロード** を押して、JSONファイルをダウンロードし、以下のコードと同じディレクトリに client_secrets.json という名前で置く

# サンプルコード

```ruby:Gemfile
source 'http://rubygems.org'
 
gem 'google-api-client', '>= 0.6'
gem 'google_drive'
```

```text:.gitignore
client_secrets.json
credential-oauth2.json
```

```ruby:sample.rb
#!/usr/bin/env ruby
#
# ref: https://github.com/google/google-api-ruby-client-samples/blob/master/drive/drive.rb
#
require 'rubygems'
require 'google/api_client'
require 'google/api_client/client_secrets'
require 'google/api_client/auth/file_storage'
require 'google/api_client/auth/installed_app'
require 'google_drive'
require 'pp'
 
# 認証情報のキャッシュファイル。gitリポジトリに入れない
CREDENTIAL_STORE_FILE = "credential-oauth2.json"
 
def setup()
  client = Google::APIClient.new(:application_name => 'Ruby spreadsheet sample',
      :application_version => '1.0.0')
 
  # 認証情報をファイルにキャッシュする
  # これによりaccess tokenがexpireしてもpromptが出ない
  # 注意: 複数ユーザ、複数プロセスでの利用には向かない
  file_storage = Google::APIClient::FileStorage.new(CREDENTIAL_STORE_FILE)
  if file_storage.authorization.nil?
    # client_secrets.jsonを読み込む
    # Google::APIClient::ClientSecrets.load(
    #   'config/client_secrets.json'
    # ) 
    # みたいに任意パスに置くことも可能
    client_secrets = Google::APIClient::ClientSecrets.load
  
    # Installed App 用のヘルパを使って認証する
    # 初回実行時のみブラウザにリダイレクトされる
    flow = Google::APIClient::InstalledAppFlow.new(
      :client_id => client_secrets.client_id,
      :client_secret => client_secrets.client_secret,
      :scope => %w(
        https://www.googleapis.com/auth/drive
        https://docs.google.com/feeds/
        https://docs.googleusercontent.com/
        https://spreadsheets.google.com/feeds/
      ),
    )
    client.authorization = flow.authorize(file_storage)
  else
    client.authorization = file_storage.authorization
  end
 
  return client
end
 
client = setup()
session = GoogleDrive.login_with_oauth(client.authorization.access_token)
ws = session.spreadsheet_by_key("YOUR_SPREADSHEET_ID_HERE").worksheets[0]
 
# dump a cell
pp ws[1,1] 
 
# update a cell
ws[5,5] = "new"
ws.save
 
# dump all cells
pp ws.rows
```

# Next step

[google-drive-ruby](https://github.com/gimite/google-drive-ruby) を参考にspreadsheetを操作していくことになります

# ちなみに...

この背景にある個人的な目的は、cronでspreadsheetをバッチ更新したかったのです。cron(=CLIツール)でどうやって OAuth クリアするんだっけ.... ということでこうなりました。

他方、1回目の実行ではブラウザが必要です。でも実行したいのはCLIオンリーなサーバ。さてどうしたものか。自分は一度 Mac で実行し token を取得して `credential-oauth2.json` を対象サーバにコピーしました。

ちなみに、CLIオンリーなサーバ上で1回目実行するとCLIブラウザが立ち上がりますが、自分はうまく出来ませんでした。

いずれにせよ、コピーする方法はいいやり方でない気がします。もし他にいいやり方があれば教えていただきたいです!



# 参考

* [google/google-api-ruby-client-samples/drive](https://github.com/google/google-api-ruby-client-samples/tree/master/drive)
* [google-drive-ruby](https://github.com/gimite/google-drive-ruby)