
お金をかけずに問い合わせフォームを構築する方法
問い合わせフォームなど、無料で設けることはできないか、考えてみた。
- 基本的にお金はかけたくない
- が、問い合わせが入ったときは通知がほしい(メールがベスト)
- 問い合わせ内容など、管理画面も自分では作りたくない
Google APIの準備
まずはGoogle Drive APIとGoogle Sheets APIを使えるようにしましょう。
Google Cloudでプロジェクトを作成後、サイドメニューから「APIとサービス」>「有効なAPIとサービス」を選択します。

その後は「Google Drive API」と「Google Sheets API」を検索し、それぞれ「有効にする」を押しましょう。

以下はDrive APIの方。すでに有効にした後の画像です。

サービスアカウントを作成する
Google CloudのAPIを使用するためのサービスアカウントを作成します。このサービスアカウントの認証情報を使用して、自分が用意したプログラムはスプレッドシートへ書き込みをすることになります。
「IAMと管理」>「サービスアカウント」の画面から作成ボタンを押し、お好みのサービスアカウント名を設定します。終わったら「完了」を押しましょう。

作成したサービスアカウントの詳細画面を開き、「鍵」のタブを表示させたら「キーを追加」>「新しい鍵を作成」を選択します。

特に理由がない場合はJSONでよいと思います。「作成」を押しましょう。これでサービスアカウントの認証情報がローカルにダウンロードされたと思います。
このファイルは大事にとっておきましょう。

サービスアカウントへの権限付与
サービスアカウントがスプレッドシートを利用できるように権限を付与します。書き込みが必要な場合は「編集」権限を付与しておきましょう。
対象のスプレッドシートから「共有」ボタンを押し、サービスアカウントの名前を入力して権限を付与します。普通にユーザーへ権限付与するやり方と同じです。
これでAPIを利用する準備が整いました!

google_drive gemを追加する
ここからはrailsの調整になります。まずはgoogle_driveのgemを追加しましょう。
$ bundle add --optimistic google_drive
サービスアカウントの情報を設定する
環境変数として配置するなど、いくつか方法はあると思いますが今回はcredentialsを使おうと思います。
先ほど取得したサービスアカウントのファイルの中身のうち、private_keyの部分をbase64でエンコードしておいてください。貼り付けたり、環境変数に含めるのに都合がいいです。
それをcredentialsの中に設定しておきます。
$ cat {サービスアカウントのjson}
{
"type": "service_account",
"project_id": "aaa",
"private_key_id": "bbb",
"private_key": "-----BEGIN PRIVATE KEY-----\n.....\n-----END PRIVATE KEY-----\n", << この中身をファイルとして保存
"client_email": "ccc",
"client_id": "ddd",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "eee",
"universe_domain": "googleapis.com"
}
$ base64 -i {private_keyの値を記載したファイル}
成功するとエンコードしたものが出力される。それをコピー
$ EDITOR=vim bin/rails credentials:edit
エディタが立ち上がったら、base64でデコードした中身を設定して保存おきましょう。
google_drive:
client_email: {ここにサービスアカウント名}
private_key: {ここにbase64エンコードした内容}
Google Driveを利用するmoduleの作成
google_drive_connectableという名前で汎用moduleを作りました。これをincludeすればgoogle_drive_sessionを介してどのクラスからでもスプレッドシートへアクセスすることができます。
require 'google_drive'
module GoogleDriveConnectable
def google_drive_session
@google_drive_session ||= create_drive_session
end
private
def create_drive_session
sio = StringIO.new({ client_email:, private_key: }.to_json)
GoogleDrive::Session.from_service_account_key(sio, 'https://www.googleapis.com/auth/drive')
end
def client_email
Rails.application.credentials.dig(:google_drive, :client_email)
end
def private_key
Base64.decode64(Rails.application.credentials.dig(:google_drive, :private_key)).gsub('\\n', "\n")
end
end
呼び出す方も書いてみましょう。あくまで一例です。スプレッドシートのidも先ほどのcredentialsに格納するようにしています。あとはこのクラスを任意の場所から呼び出して実行すればスプレッドシートへ書き込みをすることができます。
module Contacts
class SpreadsheetWriter
include GoogleDriveConnectable
class << self
def call(contact)
new(contact).call
end
end
def initialize(contact)
@contact = contact
end
def call
next_row = client_ws.num_rows + 1
client_ws[next_row, 1] = Time.current.strftime('%Y/%m/%d %H:%M:%S')
client_ws[next_row, 2] = @contact['name']
client_ws[next_row, 3] = @contact['email']
client_ws.save
end
private
def client_ws
@client_ws ||= create_client_ws
end
def create_client_ws
google_drive_session.spreadsheet_by_key(sheet_id).worksheet_by_title(sheet_name)
end
def sheet_name
'シート1'
end
def sheet_id
Rails.application.credentials.dig(:google_drive, :sheet_id)
end
end
end
スプレッドシートの更新通知を有効にする
最後に問い合わせが入った際の通知をメールで受け取れるようにしておきましょう。
スプレッドシートのメニューから「ツール」>「通知設定」>「編集通知」を選択します。

あとは、通知の頻度やトリガーを設定して完了です。

このやり方ならデータベースを用意しなくても気軽かつ無料でデータを保存でき、通知も受け取ることが可能となります。
問い合わせフォームくらいの規模であれば、これでOKなケースは結構ありそうです。
ただし、通知の宛先はスプレッドシートのオーナーに限られてしまう制約があります。
複数のメールアドレスに送信したい場合は別の方法を採用することになるでしょう。