【Ruby on Rails】RailsからGoogle Calendar APIを使用してGoogleカレンダーを操作する(後編)

こんにちは、株式会社Pentagonでエンジニアをしているakitoshigaと申します。
この記事は【Ruby on Rails】RailsからGoogle Calendar APIを使用してGoogleカレンダーを操作する(前編)の続きの記事となっています。

前編の記事では、Googleカレンダーの登録・更新・削除などの操作をRuby on Rails(以下Rails)で行うための、Google Cloud Projectの設定を行いました。

後編の記事では、Railsの設定やサンプルコードを解説していきます!

【こんな人に読んで欲しい】

  • RailsからGoogleカレンダーを操作したい人
  • その他GoogleのリソースをRailsから操作したい人

【この記事を読むメリット】

  • RailsからGoogleカレンダーの操作をする方法がわかる!
  • 実装の過程でハマった時に確認するポイントがわかる!
目次

検証環境・前提条件

検証環境

  • Ruby バージョン3.2.2
  • Ruby on Rails バージョン7.0.6

前提条件

  • 前編で紹介したGoogle Cloud Projectの設定が完了していること

Gemfileの追加

GoogleからAPIを利用するためのGemが提供されています。
今回使用するのは下記の3つです。

今回検証した環境では、Gemfileに下記のように設定しました。

gem 'google-api-client', '~> 0.53.0'
gem 'google-apis-calendar_v3', '~> 0.5.0'
gem 'googleauth', '~> 1.7', require: 'googleauth/stores/file_token_store'

'googleauth/stores/file_token_store'requireしているのがポイントです。
GemfileにGemを配置したらターミナル上でbundle installを実行してください。

サンプルコード

利用するのは下記の3つのクラスです。

  1. Google::Auth::UserAuthorizer
    • APIの認証周りを管理する
  2. Google::Apis::CalendarV3::CalendarService
    • GoogleカレンダーのAPI操作を行うクライアント
  3. Google::Apis::CalendarV3::Event
    • イベントそのもの

「イベント」とは、Googleカレンダーのひとつひとつの予定を指しています。
Googleカレンダー以外のリソースを扱いたい場合は、Google::Apisを参考にしてください。

認可サーバーからユーザーのAPIトークンを取得する

Googleカレンダーをはじめとしたユーザーのリソースを操作するには、そのユーザーのGoogleアカウントと紐づいたAPIトークンが必要です。

APIトークンを取得するには、ユーザーに実際にブラウザを操作してもらって、Railsがユーザーに代わってリソースの操作を行うことを許可してもらう必要があります。

また、Rails内で対象のユーザーと取得したAPIトークンを紐付ける必要があります。
サンプルコードでは、ユーザーがRails内でアカウント登録をしていると仮定しています。
Rails内で管理しているユーザーのIDを主キーとして、取得したAPIトークンと紐づけています。

リソース使用許可の操作をしてもらうGoogleのページのリンクを取得して、ビューに表示します。

token_path = 'token.yml' # ユーザーのAPIトークンの保存先
scope = Google::Apis::CalendarV3::AUTH_CALENDAR_EVENTS # Google Cloudコンソールで設定したスコープ
callback_path = '/google_calendar/callback' # Google Cloudコンソールで設定したリダイレクトURIのパス部分

oauth_client = Google::Auth::UserAuthorizer.new(
 Google::Auth::ClientId.from_file(token_path),
 scope,
 Google::Auth::Stores::FileTokenStore.new(file: token_path),
 callback_path
)

base_url = 'http://localhost:3000' # Google Cloudコンソールで設定したリダイレクトURIのベース部分
@authorization_url = oauth_client.get_authorization_url(base_url: base_url)

また、先ほどダウンロードしたJSONファイルをRailsのディレクトリの中に配置してください。
サンプルコードではプロジェクトのルートディレクトリ直下に配置している想定で進めています。

ビュー側で導線を用意します。

<div>
  <%= button_to '認証する', @authorization_url %>
</div>

導線として配置したボタンを押下すると、ユーザーが登録しているGoogleアカウントの一覧が表示されます。
Googleアカウントの一覧から、Google Cloudコンソールで登録したアカウントを選択します。

アカウントを選択すると、次のような画面が表示されるので、「続行」を押下します。

Google Cloudコンソールで作成したOAuth同意画面が表示されるので、再度「続行」を押下します。

すると、Google Cloudコンソールで登録したリダイレクトURIに、ユーザーのAPIトークン取得のための認可コードをパラメーターに付与された状態でリクエストされます。

リダイレクトURIにマッピングしたアクションで下記のようにトークンを保存します。

# 認可サーバーから発行された認可コードを使用して、APIトークンを保存する

code = params[:code] # 認可コード

oauth_client.get_and_store_credentials_from_code( # Google::Auth::UserAuthorizerのインスタンス
 user_id: current_user.id, # ログイン済みのユーザーと仮定して、ユーザーIDを渡す
 code: code,
 base_url: base_url
)

サンプルコード内の既出の変数は代入を省略していますが、先ほどのサンプルコードと同じ内容です。
コードの見通しが悪くなるため、以降も既出の変数に関しては代入部分を省略しています。

注意点として、ユーザーがもし許可をしなかった場合は{ error: ’access_denied’ }といったパラメーターを付与された状態でリダイレクトされます。
実際にサービスに組み込む場合は適切なハンドリングが必要です。

これでtoken.ymlに認可したユーザーのAPIトークンが保存されました!
このAPIトークンを使用して、Googleカレンダーの操作を行っていきます。

イベントの登録

イベントの登録にはGoogle::Apis::CalendarV3::CalendarServiceと、Google::Apis::CalendarV3::Eventのインスタンスが必要です。
最初にGoogle::Apis::CalendarV3::CalendarServiceのインスタンスを生成します。
Google::Apis::CalendarV3::CalendarServiceがユーザーのGoogleカレンダーの操作をするには、APIトークンの情報が必要です。

APIトークンは、Google::Auth::UserAuthorizer#get_credentialsの引数にユーザーIDを渡すことで取得できます。

credentials = oauth_client.get_credentials(current_user.id)

このcredentialsGoogle::Apis::CalendarV3::CalendarServiceのインスタンスに渡すことで、そのユーザーのGoogleカレンダーを操作できるようになります。

calendar_service = Google::Apis::CalendarV3::CalendarService.new
calendar_service.client_options.application_name = 'サンプルアプリケーション' # Google Cloudコンソールで登録したアプリケーション名
calendar_service.authorization = credentials # Google::Auth::UserAuthorizerから受け取った認証情報

次にGoogle::Apis::CalendarV3::Eventのインスタンスを生成します。
このインスタンスに、イベントに登録したい内容をコンストラクタの引数として渡します。

event = Google::Apis::CalendarV3::Event.new(
  summary: ‘イベントのタイトル’, # イベントのタイトル
  location: 'イベントの場所', # 場所
  description: 'イベントの説明文。', # 説明
  start: Google::Apis::CalendarV3::EventDateTime.new( # 開始日時
    date_time: Time.current.rfc3339, # RFC3339のフォーマット指定あり
    time_zone: 'Asia/Tokyo' #タイムゾーン
  ),
  end: Google::Apis::CalendarV3::EventDateTime.new( # 終了日時
    date_time: Time.current.since(3.hour).rfc3339,
    time_zone: 'Asia/Tokyo'
  )
)

その他イベントに登録できる内容は下記に記載されています。
Class: Google::Apis::CalendarV3::Event

このインスタンスを先ほど生成したGoogle::Apis::CalendarV3::CalendarServiceのメソッド#insert_eventの引数に、カレンダーIDとともに渡します。

calendar_id = 'primary' # カレンダーID。デフォルトはprimary

registered_event = calendar_service.insert_event(calendar_id, event)

カレンダーIDとは、ユーザーが管理するGoogleカレンダーの識別子のことで、デフォルトは’primary’です。

#insert_eventの戻り値でサンプルコードで実際に登録されたGoogle::Apis::CalendarV3::Eventのインスタンスが返却されます。

このインスタンスのプロパティにidというイベントの識別子が登録されています。

また、イベントの更新・削除に必要となるためサンプルコードでは変数registered_eventに登録したイベントのインスタンスを代入している形で進めます。

実際にサンプルコードで登録したイベントです。


次はイベントの更新を行っていきます。

イベントの更新

イベントの更新も、登録した時と同様にGoogle::Apis::CalendarV3::CalendarServiceと、Google::Apis::CalendarV3::Eventのインスタンスを使用します。

Google::Apis::CalendarV3::CalendarService#update_eventの引数にカレンダーID、イベントID、Google::Apis::CalendarV3::Eventのインスタンスを渡すことでイベントの更新ができます。

注意点として、イベントの更新は更新したい差分となる箇所の情報のみではなくGoogle::Apis::CalendarV3::Eventのインスタンスが丸ごと必要となります。

ちなみに、Google::Apis::CalendarV3::CalendarServiceには#get_eventというAPIが用意されており、カレンダーIDとイベントIDからユーザーの登録しているイベントの取得も可能です。

registered_event.summary = '更新されたイベント'
event_id = registered_event.id

calendar_service.update_event(
 calendar_id,
 event_id, # Google::Apis::CalendarV3::Event#id
 event   # Google::Apis::CalendarV3::Event
)

サンプルコードで更新したイベントです。

イベントの削除

イベントの削除はGoogle::Apis::CalendarV3::CalendarService#delete_eventの引数にカレンダーIDとイベントIDを渡すだけです。

calendar_service.delete_event(calendar_id, registered_event.id)

これでイベントの削除は完了です。

まとめ

Google Cloudコンソール上での設定や、APIトークンを取得するまでの工程など、結構手間がかかるなという印象でした。
困った時は公式のドキュメントを確認するのが一番早そうです。

みなさんがGoogleカレンダーをはじめとしたGoogleのリソースをAPIで扱う時の一助となれば嬉しいです!

採用情報はこちら
目次