Railsからスプレッドシートを定時で書き換える

## はじめに
サービスのKPIなどをスプレッドシートで管理することが多いとは思いますが、毎回データ取ってスプレッドシートに書き込んで、、をやってるとまあまあ時間の無駄なのでRailsアプリから直接スプレッドシートシートに書き込むようにしました。
加えてKPIの計測なので毎朝データを更新できるようにバッチも組むようにしました。

今回には以下を使っています。

- Rails 5.2
- gem 'google_drive'

## 実装
### 作るもの
Railsのデータベースから当月に会員登録したユーザーの数を日別で取得するようにします。
ユーザーは User モデルとします。
### 認証情報の取得
API経由でスプレッドシートを編集するために認証情報が必要なので <a href='https://console.developers.google.com/' target="_blank">Google Developers Console</a> で情報を取得します。

#### プロジェクトの作成
ますはプロジェクトを作成します。
<img width="1673" alt="スクリーンショット 2019-07-07 11.54.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79526/ad209e0f-ebb9-f843-3c65-76b0f1b56103.png">
<img width="572" alt="スクリーンショット 2019-07-07 11.56.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79526/0cc97eb6-8fbc-b793-c0ee-26c45ffafb21.png">

#### APIの有効化
続いてスプレッドシートのAPIの利用を有効化するためにライブラリからスプレッドシートを検索して有効化します。
<img width="1145" alt="スクリーンショット 2019-07-07 11.57.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79526/5a8c387b-9ddb-1fc9-afa6-01a2b6b44ce1.png">
<img width="982" alt="スクリーンショット 2019-07-07 12.01.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79526/546ff01d-72f6-880b-94c6-3a319be55950.png">

#### 認証情報の作成
まずはOAuth同意画面で操作します。アプリケーション等を埋めて保存します。
<img width="1113" alt="スクリーンショット 2019-07-07 12.07.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79526/1e2557a3-c1ec-f712-b844-9d25e734b5b3.png">

つづいてOAuthクライアントを作成していきます。
<img width="1670" alt="スクリーンショット 2019-07-07 12.08.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79526/91ff3f9e-ecf5-3c2d-3c11-f6c0e0b21b00.png">
<img width="693" alt="スクリーンショット 2019-07-07 12.09.17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79526/863574ca-e492-5945-e892-59a93c48d5b7.png">

作成したクライアントのリストから名前をクリックするとクライアントIDとクライアントシークレットを確認できます。
<img width="1670" alt="スクリーンショット 2019-07-07 12.10.00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79526/3b757825-ede8-92bd-c8ca-990bde4e01ef.png">

#### リフレッシュトークンの取得
つづいて先程作成したクライアントの情報をもとにリフレッシュトークンを取得します。
書くの面倒くさくなってしまったのでこちらのやり方は<a href="https://qiita.com/iwaseasahi/items/2363dc1d246bc06baeae#5%E3%82%AF%E3%82%A8%E3%83%AA%E3%83%91%E3%83%A9%E3%83%A1%E3%83%BC%E3%82%BF%E3%82%92%E8%BF%BD%E5%8A%A0%E3%81%97%E3%81%9Furl%E3%81%AB%E3%83%96%E3%83%A9%E3%82%A6%E3%82%B6%E3%81%A7%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9" target="_blank">この記事</a>を参考にしてみてください。


### Rails側の実装
今回はもろもろの処理をジョブの中に書いていきます。

Google API を今回の処理以外でも使う可能性を加味して `ApplicationJob` に API の認証の処理を書き、他のジョブでも呼び出せるようにしました。(使う可能性を加味してというか、私の場合は複数使っているため)

```app/jobs/application_job.rb
class ApplicationJob < ActiveJob::Base

  def google_drive
    credentials = Google::Auth::UserRefreshCredentials.new(
      client_id: ENV['KPI_SHEET_CLIENT_ID'],
      client_secret: ENV['KPI_SHEET_CLIENT_SECRET'],
      scope: %w(https://www.googleapis.com/auth/drive https://spreadsheets.google.com/feeds/),
      redirect_uri: 'http://storys.jp'
    )
    credentials.refresh_token = ENV['KPI_SHEET_REFRESH_TOKEN']
    credentials.fetch_access_token!
    GoogleDrive::Session.from_credentials(credentials)
  end
end
```

実際にスプレッドシートに書き込む処理は以下です。
`ws[1, 1]` はシートの1行目の1列目、`ws[1, 2]`は1行目の2列目です。
同じように`ws[2, 1]`は2行目の1列目になります。

```app/jobs/export_kpi_job.rb
class ExportKpiJob < ApplicationJob

  def perform
    spreadsheet = google_drive.spreadsheet_by_key('スプレッドシートのキー')
    ws = spreadsheet.worksheet_by_title('該当のシートの名前')

    ws[1, 1] = ''
    ws[1, 2] = '新規登録ユーザー数'

    current_date = Date.current
    beginning_day_of_month = current_date.beginning_of_month
    end_day_of_month = current_date.end_of_month

    (beginning_day_of_month..end_day_of_month).each.with_index(2) do |date|
      ws[index, 1] = date
      ws[index, 2] = Users.where(created_at: date.beginning_of_day..date.end_of_month)
    end

    ws.save
  end
end
```

### 定時処理の設定
定時処理には `gem 'whenever'` を使います。
whenever自体の使い方はこちらを参考にしてください。

まずはタスクの作成

```lib/tasks/rails_sample.rake
namespace :rails_sample do
  desc 'KPIをスプレッドシートに吐き出す'
  task :export_kpi => :environment do
    ExportKpiJob.perform_now
  end
end
```

今回は毎朝4時にタスクが走るようにします。

```config/schedule.rb
every 1.day, at: '4:00 am', role: [:app] do
  rake 'rails_sample:export_kpi'
end
```

## まとめ
以上でRailsからスプレッドシートを定時で書き換えるようにできました。
こういう小さな自動化を含めて、自分はもちろん他の人の仕事の効率を上げてあげることがエンジニアのできる貢献の1つかと思うので今後も続けたい所存。