Google_driveにデータを書き込む
Ruby on Railsでやります。
Google_driveというGemをインストール
参考:google_drive_ruby
Readmeにそれっぽい感じで書いてあるんだけど、あんまり役立たない。基本的なことだけ書いてあるのでそれを一所懸命ゴリゴリする想定でいてください。
gem 'google_drive'
ちなみに試してた環境はRails 5.0.1です。いつもの、bundle installで。
GoogleDriveApiのリフレッシュトークンの取得
参考:Google API OAuth2.0のアクセストークン&リフレッシュトークン取得手順 2017年2月版 - Qiita
GoogleDriveAPIの取得方法は上記がすごく丁寧に載せてくださってます。
ただし、GoogleさんはガンガンUIを変えていくので、僕の試した2017年03月段階ですでに上記サイトのスクリーンショットとは異なっていました。
とりあえずここを超えないとGoogleDriveに接続できない(つまりSpreadsheetに接続できない)。
頑張れ。
GoogleDriveとの接続情報を保存しておく
config/settings.ymlに入れておくのがいい。
("config"というgem使ってください)
google_drive:
client_id: 888*******21-9**************pphq9kdo6.apps.googleusercontent.com
client_secret: d5e*******************bCn
code: 4/2Icegy****************ytq0boS8#
refresh_token: 1/MxzVY-0G7Xu*******************aoHLY
access_token: ya29.GlsCBNH**************Gc_WcIqXufnqBo2ZSLD*******GFJA5UpCpp1l
上記は一例(*は伏せ字にしてるだけ。本当はアルファベットや記号)。
先程頑張って手に入れたrefresh_tokenなどを書き込む。
なお、必要になるのはclient_id、client_secret、refresh_tokenだけ。
codeはそのtokenを取るように必要で、access_tokenは変わってしまうのでrefresh_tokenしか使わない(ここではなんとなく取っといただけ)。
ActiveJobの作成
さてここからRailsのActiveJobを作っていきます。
GoogleDriveとの接続
private
def google_drive
credentials = Google::Auth::UserRefreshCredentials.new(
client_id: Settings.google_drive.client_id,
client_secret: Settings.google_drive.client_secret,
scope: %w(https://www.googleapis.com/auth/drive https://spreadsheets.google.com/feeds/),
redirect_uri: 'http://example.com/redirect'
)
credentials.refresh_token = Settings.google_drive.refresh_token
credentials.fetch_access_token!
GoogleDrive::Session.from_credentials(credentials)
end
こちらをコピペでお使いくださいw
さっきまでの手順でちゃんとrefresh_tokenやclient_idを作ってあれば、上記がコピペでいけます。
2014年ぐらいまでは、接続するためにgmailアドレスとそのパスワードを直書きするという仕様(!)でしたが、ちゃんとauthになっております。
redirect_uriはサンプルっぽく書いてありますが、GoogleDriveAPIのキーを発行するときに入力したはずのredirect_uriです。ぶっちゃけなんでもOKみたい。
スプレッドシートのシート作成
プライベートメソッドでGoogleDriveとの接続は作ったのでスプレッドシートを作成します。
def perform(ws_id = nil)
google_drive
ws = google_drive.spreadsheet_by_key(ws_id)
ws_title = "シート名"
ws = ws.worksheet_by_title(ws_title) || ws.add_worksheet(ws_title)
insert_header(ws)
end
def perform を作成
def performを作成します。performはActiveJobを普通にgenerateしたら出来上がります。(参考:Active Job の基礎)
なおここでは、ws_id(wsはワークシート)というGoogleスプレッドシートのファイル固有のIDをparamsで渡せるようにしておきます。
次に、privateメソッドで作っておいたgoogle_driveを呼び出して接続。
その次に、wsという変数にスプレッドシートのファイルを指定します。
ws_id にはGoogleスプレッドシートのURLに出てくる、「https://docs.google.com/spreadsheets/d/1Mb4tYxcvbnmyu-RPwertyuiovhjk7Cdi6Mhwo2rb_m84/edit
」のd/の後ろの文字列を渡します(1Mb4tYxcvbnmyu-RPwertyuiovhjk7Cdi6Mhwo2rb_m84の部分)。これがws_idです。
※でたらめのURLですよ
シートの名前をつけたい場合に、 ws_title = "シート名" を変更します。
文字通りスプレッドシート内のシート名を変えることができます。
paramsで渡したりもできるし、つけなくてもいいです。任意。
そして、
ws = ws.worksheet_by_title(ws_title) || ws.add_worksheet(ws_title)
は、かなり便利な一行。
シートがあったらそこにデータを追加するし、シートがなかったらシート作成ができる。
worksheet_by_title(ws_title)が既存。ws.add_worksheet(ws_title)が追加。
※add_worksheetとかいうメソッドを探すのに超時間かかったのは内緒だ。
privateメソッドに「insert_header」として、ヘッダー追加できるようにする。
private
def insert_header(ws)
ws[1, 1] = "No"
ws[1, 2] = "名前"
ws[1, 3] = "URL"
ws[1, 4] = "電話番号"
ws[1, 5] = "住所"
ws[1, 6] = "最終更新日"
end
上記適当。
ws[1, 1]は、ワークシートの1行目、1列目(エクセルでいうと1行目のA列)。
ws[1, 4]は、ワークシートの1行目、4列目(エクセルでいうと1行目のD列)。
wsの後に配列っぽく表記することで行列を指定できるのは中々表現がわかりやすくて良い。
さあ、配列ぶっこもう
@array.each do |r|
num_rows = ws.num_rows
ws[num_rows + 1, 1] = num_rows
ws[num_rows + 1, 2] = r.name
ws[num_rows + 1, 3] = r.url
ws[num_rows + 1, 4] = r.tel
ws[num_rows + 1, 5] = r.address
ws[num_rows + 1, 6] = "#{Time.current.strftime('%Y年%m月%d日 %T')}"
end
ws.save
上記で、eachぶん回すと1行ずつ6列に値がぼこぼこ入っていく形となります。
なお、
ws.num_rowsは、レコード数を取得。
ws.num_colsは、カラム数を取得。ここでは使ってないけど。
ws.saveはシートの保存。
ws.reloadはシートの最新を取得(要はF5です)。
まとめ
ということで、ざっとまとめると、
class WsSaveJob < ApplicationJob
queue_as :default
def perform(ws_id = nil)
google_drive
ws = google_drive.spreadsheet_by_key(ws_id)
ws_title = "シート名"
ws = ws.worksheet_by_title(ws_title) || ws.add_worksheet(ws_title)
insert_header(ws)
@array.each do |r|
num_rows = ws.num_rows
ws[num_rows + 1, 1] = num_rows
ws[num_rows + 1, 2] = r.name
ws[num_rows + 1, 3] = r.url
ws[num_rows + 1, 4] = r.tel
ws[num_rows + 1, 5] = r.address
ws[num_rows + 1, 6] = "#{Time.current.strftime('%Y年%m月%d日 %T')}"
end
ws.save
end
private
def google_drive
credentials = Google::Auth::UserRefreshCredentials.new(
client_id: Settings.google_drive.client_id,
client_secret: Settings.google_drive.client_secret,
scope: %w(https://www.googleapis.com/auth/drive https://spreadsheets.google.com/feeds/),
redirect_uri: 'http://example.com/redirect'
)
credentials.refresh_token = Settings.google_drive.refresh_token
credentials.fetch_access_token!
GoogleDrive::Session.from_credentials(credentials)
end
def insert_header(ws)
ws[1, 1] = "No"
ws[1, 2] = "名前"
ws[1, 3] = "URL"
ws[1, 4] = "電話番号"
ws[1, 5] = "住所"
ws[1, 6] = "最終更新日"
end
以上。
今回参考にしたサイトは以下。ありがとうございました。
・gimite/google-drive-ruby
・Google API OAuth2.0のアクセストークン&リフレッシュトークン取得手順 2017年2月版
・Google DriveのスプレッドシートにRubyでアクセスする方法
・Active Job の基礎