RubyからGoogle APIにアクセスするのは半端なくめんどくさい

RubyからGoogleが提供しているAPIを利用するには`google-api-ruby-client gem`を使う必要があるが、APIの前提知識、複雑な認証処理、Rubyっぽくないインターフェースなど、`google-api-ruby-client gem`を利用するためのハードルはなかなか高い。

毎年のように調べ直すことにさすがに疲れたので、来年に向けて、現時点で分かっているGoogle APIの利用方法を書き残しておく。

## 最終的なRubyのコードはこちら

Google AnalyticsのAPIにRubyからアクセスするコードは下記の通り。


```ruby
require 'googleauth'
require 'googleauth/stores/file_token_store'
require 'google/apis/analytics_v3'

OOB_URI = 'urn:ietf:wg:oauth:2.0:oob'

token_store_file = 'credentials.yaml'
scope = Google::Apis::AnalyticsV3::AUTH_ANALYTICS # == "https://www.googleapis.com/auth/analytics"
client_id = Google::Auth::ClientId.from_file('client_secret.json') # ダウンロードしたファイル


token_store = Google::Auth::Stores::FileTokenStore.new(file: token_store_file)
authorizer = Google::Auth::UserAuthorizer.new(client_id, scope, token_store)

credentials = authorizer.get_credentials('default')
if credentials.nil?
  # 初回のみ必要な処理。ブラウザでURLを開き承認すると、credentials.yamlが作成される。
  # 次回以降はこのymlファイルを使って自動で認証が進む
  url = authorizer.get_authorization_url(base_url: OOB_URI)
  puts "Open #{url} in your browser and enter the resulting code:"
  code = gets
  credentials = authorizer.get_and_store_credentials_from_code(user_id: 'default', code: code, base_url: OOB_URI)
end

analytics = Google::Apis::AnalyticsV3::AnalyticsService.new
analytics.authorization = credentials

# ここまでの処理がうまくいっていれば、結果が表示される
profile_id = [GAのPROFILE ID]
analytics.get_realtime_data("ga:#{profile_id}", 'rt:activeUsers').totals_for_all_results['rt:activeUsers']
```

**今回やりたいのは、Google AnalyticsやGoogle DriveのAPIにRubyからアクセスすること。**

## 認証情報の作成

まず初めに、Rubyを書く以前の段階ですら分かりづらい点がたくさんある。Googleの認証情報作成ウイザードは非常に使いづらく、初見ではどの選択肢を選べばよいのかまったく分からない。

<img width="619" alt="スクリーンショット 2019-03-03 8.58.17.png" src="https://qiita-image-store.s3.amazonaws.com/0/33011/ac4dce15-8f59-95f0-9f04-edeac9e47a45.png">


結論から言うと、**ウイザードをスキップして直接作るのが一番簡単**ではあるが、途中に出てくる選択肢にどのような意味があるのかを備忘録として書いておく。

### 使用するAPIの欄

一例として下記のような選択肢が表示される。このどれを選ぶのかによってその後の選択肢が変わるのだが、「サービスアカウント」や「APIを使用する場所」などの現時点ではよく分からない説明がでてきて困惑する。

この選択肢で正解を選んだとしても、「APIを使用する場所」の選択肢を間違えると結局違った種類のキーが作成されてしまう点に注意が必要。

- Analytics API
- BigQuery API
- URL Shortener API
- （その他たくさん）

### APIを呼び出す場所の欄

下記の選択肢が表示される。RubyからGoogle APIにアクセスするので必然的にウェブサーバー、その他のUI、その他の非UIのいずれかを選ぶことになるのだが、現時点ではその違いが分からず困惑する。結論としてはこの3つのどれを選んでも同じになる。

- ウェブブラウザ（Javascript）
- ウェブサーバー（node.js、Tomcatなど）
- Android
- iOS
- Chromeアプリケーション
- その他のUI（Windows、CLIツールなど）
- その他の非UI（cronジョブ、デーモンなど）

### アクセスするデータの種類

下記の2種類が選択肢として表示され、ユーザーデータを選ぶとOAuth2.0 クライアントID、アプリケーションデータを選ぶとサービスアカウントキーが作成される。こちらも、補足説明が一切無く困惑する要因には事欠かない。

- ユーザーデータ
- アプリケーションデータ

上記の選択肢をどれを選んだとしても、次のステップで新しい用語がでてきて困惑することになる。次の困惑ポイントとして、作成できるキーの種類について説明する。


## APIキー, OAuth2.0 クライアントID, サービスアカウントキーの違い

Google APIには複数種類の認証方法が存在し、それぞれが何を意味しているのかを調べるだけでも一苦労する。まず初めに、自分が使うべき認証方法はどれなのかが分かるようになる必要がある。

### APIキー

APIキーを使ってアクセスできるのは、Googleマップ、Google翻訳、Google URL短縮など。

大雑把に言うと、ユーザーのログイン情報が必要なく、入力データを与えると何らかの変換結果が返ってくるだけのAPIには**APIキー**を使ってアクセスすることになる。


### OAuth2.0 クライアントID

OAuth2.0 クライアントIDを使ってアクセスできるのは、Gmail, Google Drive, Google Analyticsなど。

ログインしているユーザーの情報に依存するAPIを利用するには**OAuth2.0 クライアントID**を使う必要がある。

### サービスアカウントキー

サービスアカウントキーを使ってアクセスできるのは、Android Publisher、Google Cloud Platformなど。

ログインしているユーザーには依存しないが何らかのデータ操作が必要なAPIを利用するにはサービスアカウントキーを利用する必要がある。

### 今回必要なのは OAuth2.0 クライアントID

ここまでの知識があって初めて、今回の用途にはOAuth2.0 クライアントIDが必要だということが分かる。

これさえ分かれば、後はOAuth2.0 クライアントIDをウイザードではなく直接作ってしまえばよい。

<img width="633" alt="スクリーンショット 2019-03-03 8.56.52.png" src="https://qiita-image-store.s3.amazonaws.com/0/33011/076a8922-5cea-0dfc-0aea-7b3786660f81.png">

ここまでがうまくいったとしても、最後にもう1つハマりポイントがある。自分がRubyを動かす場所がWebサーバー内だったとしても、「ウェブアプリケーション」を選ぶ必要がない。

この場合のウェブアプリケーションとは、**ユーザーにアクセスさせて、認証ページを使った承認処理を行った後にリダイレクトして戻ってくる**という意味。コマンドラインやWebサーバー内で利用するだけなら、「その他」を選べばよい。

<img width="638" alt="スクリーンショット 2019-03-03 9.06.22.png" src="https://qiita-image-store.s3.amazonaws.com/0/33011/fcc55bf1-dc51-b703-aeb8-f82a050ce51a.png">

ここまででようやく認証情報の作成が完了するが、初めて作成する場合は間違えた認証情報を作ってしまっていることが多いと思う。次は、自分が作成した認証情報が正しいかどうかを確認する方法を書く。

## OAuth2.0 クライアントIDを正しく作成できていることの確認方法

認証情報の作成後に下記のダイアログが表示されていれば、OAuth2.0 クライアントIDは正しく作成できている。ポイントは、クライアントIDとクライアントシークレットの記載があること。両方ともこの後必要になるのでメモしておくこと。

**注意1**
**ダイアログに記載されているように、「OAuth 同意画面」も作成しておく必要がある。たとえ利用するのが自分一人だったとしても作成する必要がある。**

<img width="505" alt="スクリーンショット 2019-03-03 9.15.18.png" src="https://qiita-image-store.s3.amazonaws.com/0/33011/cdc9385e-21ae-d2c6-49ea-a16080815276.png">

**最重要ポイント**

画面の右端のダウンロードボタンから、`client_secret_[長い文字列].json`をダウンロードする必要がある。どこにも説明が書いていないが、RubyからGoogle APIにアクセスするためにはこのファイルが必須。

<img width="274" alt="スクリーンショット 2019-03-03 9.19.20.png" src="https://qiita-image-store.s3.amazonaws.com/0/33011/33910ffd-f0bd-37ca-90b9-4808c369ad85.png">

### 間違えてサービスアカウントキーを作成している場合の確認方法

間違えてサービスアカウントキーを作成した場合にもjsonファイルのダウンロードがあり、これが非常にややこしい。

下記の3点で、自分が正しくOAuth2.0 クライアントIDを作成しているのかの確認ができる。

- 正しいjsonファイルにはファイル名にclient_secretという文字列が入っている
    - 正しいjsonファイルには`installed`というキーがある
    - 間違いのjsonファイルには`"type": "service_account"`という値がある


ようやく認証情報が作成できて一安心だが、Rubyを書き始めてからも注意点が多い。次に、Rubyを書く際の注意点を説明する。

## google-api-ruby-client gemを使ってGoogle APIにアクセスする

先に結果を書くと下記のようなコードになる。

とても短いので簡単そうに思えるが、古いバージョンの情報が根強く残っている、人よって書き方が違う、サンプルコードが不十分かつ断片的、などの理由で、このコードを初見で書くのは非常に骨の折れる作業になる。

```ruby
require 'googleauth'
require 'googleauth/stores/file_token_store'
require 'google/apis/analytics_v3'

OOB_URI = 'urn:ietf:wg:oauth:2.0:oob'

token_store_file = 'credentials.yaml'
scope = Google::Apis::AnalyticsV3::AUTH_ANALYTICS # == "https://www.googleapis.com/auth/analytics"
client_id = Google::Auth::ClientId.from_file('client_secret.json') # ダウンロードしたファイル


token_store = Google::Auth::Stores::FileTokenStore.new(file: token_store_file)
authorizer = Google::Auth::UserAuthorizer.new(client_id, scope, token_store)

credentials = authorizer.get_credentials('default')
if credentials.nil?
  # 初回のみ必要な処理。ブラウザでURLを開き承認すると、credentials.yamlが作成される。
  # 次回以降はこのymlファイルを使って自動で認証が進む
  url = authorizer.get_authorization_url(base_url: OOB_URI)
  puts "Open #{url} in your browser and enter the resulting code:"
  code = gets
  credentials = authorizer.get_and_store_credentials_from_code(user_id: 'default', code: code, base_url: OOB_URI)
end

analytics = Google::Apis::AnalyticsV3::AnalyticsService.new
analytics.authorization = credentials

# ここまでの処理がうまくいっていれば、結果が表示される
profile_id = [GAのPROFILE ID]
analytics.get_realtime_data("ga:#{profile_id}", 'rt:activeUsers').totals_for_all_results['rt:activeUsers']
```

一度認証がうまくいけば、後は下記のドキュメントを見ながら実装が可能。（ここからも長い）

- [google-api-ruby-client README](https://github.com/googleapis/google-api-ruby-client)
- [google-api-ruby-client Samples](https://github.com/googleapis/google-api-ruby-client/tree/master/samples/cli)
- [google-auth-library-ruby README](https://github.com/googleapis/google-auth-library-ruby)
- [Google API Client Libraries Ruby (Alpha)
](https://developers.google.com/api-client-library/ruby/start/get_started?hl=ja)