LoginSignup
99
57

More than 5 years have passed since last update.

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

Last updated at Posted at 2019-03-03

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

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

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

Google Analyticsの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 = [GAPROFILE ID]
analytics.get_realtime_data("ga:#{profile_id}", 'rt:activeUsers').totals_for_all_results['rt:activeUsers']

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

認証情報の作成

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

スクリーンショット 2019-03-03 8.58.17.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をウイザードではなく直接作ってしまえばよい。

スクリーンショット 2019-03-03 8.56.52.png

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

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

スクリーンショット 2019-03-03 9.06.22.png

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

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

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

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

スクリーンショット 2019-03-03 9.15.18.png

最重要ポイント

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

スクリーンショット 2019-03-03 9.19.20.png

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

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

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

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

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

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

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

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

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 = [GAPROFILE ID]
analytics.get_realtime_data("ga:#{profile_id}", 'rt:activeUsers').totals_for_all_results['rt:activeUsers']

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

99
57
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
99
57