2021年9月26日

NuxtでGoogle SpreadsheetをDB代わりに使うぞ大作戦

読了時間の目安: 5分


スプレッドシートをデータベースとして活用する方法をまとめます。

いま話題のTwitterスペースと出会えるプロダクトspaces.bz(クローズ済み)を開発しています。

GASでTwitter APIをたたいてスプレッドシートに記録するプロトタイプからはじめました。 プロトタイプのあと、このままスプレッドシートをDBとして使えれば楽なのではと考え、Nuxt + Spreadsheet構成でプロダクトを開発してみたので、体験記をまとめます。

この記事でやること

スプレッドシートからデータを取得して表示するNuxtアプリを作ります。 サンプルのスプレッドシートは以下のようなイメージ。

idnameageemail
1Test A20test_a@sample.com
2Test B30test_b@sample.com
3Test C40test_c@sample.com

スプレッドシートをJSONで返却するGASを作成

まずはスプレッドシートの情報を取得するAPIみたいなものを作っていきます。 GASでプログラムを組んでWebアプリとして公開する、をしますが、GASの方からやっていきます。

コード.js
function doGet() {
const users = getUsers()
return ContentService
.createTextOutput(JSON.stringify(users))
.setMimeType(ContentService.MimeType.JSON)
}
function getUsers() {
const ss = SpreadsheetApp.openById('スプレッドシートのID')
const sheet = ss.getSheetByName('シート名')
const rows = sheet.getDataRange().getValues()
const keys = rows.splice(0,1)[0]
const users = rows.map((row) => {
const object = {}
row.map((value, index) => {
object[keys[index]] = value
})
return object
})
return users
}

ちょこっとコードをみてみます。

doGet関数

このコードの最初の肝はdoGet関数を用いていることです。 この後Webアプリで公開すると話しましたが、doGet関数はWebアプリで公開したURLにGETリクエストが来たときに動く関数です。

Web Apps  |  Apps Script  |  Google for Developers

今回のコードではdoGet関数が動き出したらgetUsers関数を呼び出してスプレッドシートの中身をJSONに整形し返却します。

return ContentService
.createTextOutput(JSON.stringify(users))
.setMimeType(ContentService.MimeType.JSON)

getUser関数

次に、getUser関数をみてみます。

const ss = SpreadsheetApp.openById('スプレッドシートのID')

最初に対象のスプレッドシートを読み込んでいます。スプレッドシートのIDはスプレッドシートのURLからわかり、https://docs.google.com/spreadsheets/d/*****/edit*****の部分です。

const sheet = ss.getSheetByName('シート名')

次に、そのスプレッドシートのシート名のシートを持ってきます。

const rows = sheet.getDataRange().getValues()

そして、そのシートのデータが入力されているセルのデータを行単位の配列で取得します。 サンプルの例だと、rowsの値は以下のようになっています。

rows = [
['id', 'name', 'age', 'email'],
['1', 'Test A', '20', 'test_a@sample.com'],
['2', 'Test B', '30', 'test_b@sample.com'],
['3', 'Test C', '40', 'test_c@sample.com']
]
const keys = rows.splice(0,1)[0]

お次はrowsの1つ目の配列を取り出してkeysに代入しています。これによって、keysrowsは以下のようになります。

keys = ['id', 'name', 'age', 'email']
rows = [
['1', 'Test A', '20', 'test_a@sample.com'],
['2', 'Test B', '30', 'test_b@sample.com'],
['3', 'Test C', '40', 'test_c@sample.com']
]

これでkeysがjsonのkeyになり、rowsに残った項目がvalueになる未来が見えてきました。

const users = rows.map((row) => {
const object = {}
row.map((value, index) => {
object[keys[index]] = value
})
return object
})

そんな未来を実現するコードがこれです。 rows.map((row) => { 処理 })rowsから配列を一つずつ持ってきて変数rowに格納し処理を実行しています。 処理の部分でもrow.map((value, index) => { 処理2 })としてrowの要素を一つずつ取り出します。 処理2object[keys[index]] = valueとすることで各配列をオブジェクトの形に整形しています。

最終的にusersの値はこんな感じです。

users = [
{
id: 1,
name: 'Test A',
age: 20,
email: 'test_a@sample.com'
},
{
id: 2,
name: 'Test B',
age: 30,
email: 'test_b@sample.com'
},
{
id: 3,
name: 'Test C',
age: 40,
email: 'test_c@sample.com'
}
]

これを最後にreturnする関数です。

これでWebアプリを公開したときにスプレッドシートのシートをjsonで返却するGASの準備ができたので、次はWebアプリを公開していきます。

Webアプリを公開する

Web Apps  |  Apps Script  |  Google for Developers

WebサイトはGASのエディターの上部にある「デプロイ」ボタンから行います。

デプロイ

「デプロイ」>「新しいデプロイ」を選択して...。

新しいデプロイ

「種類の選択」>「ウェブアプリ」を選択して...。

設定

「新しい説明文」にわかりやすい名前(productionとかtestとか)、「次のユーザーとして実行」に「自分」を、「アクセスできるユーザー」に「全員」を設定し、「デプロイ」を選択して...。

認証

(必要な場合は)「アクセスを承認」を選択して...。

Google認証

「Google認証」して...。

Continue

「Advanced」を選択して、「<プロジェクト名>(unsafe)」を選択して...。

アクセスを許可

「Allow」して...。

デプロイ完了

完了です🎉。 「ウェブアプリ」の方に書いてあるURLがAPI(サイトとしても)公開しているURLになります。ちょっとcurlしてみましょう。

Terminal window
$ curl -L <URL>
[
{"id":1,"name":"Test A","age":20,"email":"test_a@sample.com"},
{"id":2,"name":"Test B","age":30,"email":"test_b@sample.com"},
{"id":3,"name":"Test C","age":40,"email":"test_c@sample.com"}
]

返却されていますね。

画面じゃないとわかりにくいなと思い、画像多めでお届けしました。 ってことなので、これをNuxtでの表示を作っていきます。

NuxtでAPI叩いて表示

最後に、今公開したAPIをNuxtアプリから叩いてデータを表示していきます。

まず、APIを叩くために @nuxtjs/axios を導入してきます。

Introduction - Axios Module
Terminal window
$ yarn add @nuxtjs/axios

nuxt.config.jsでモジュール登録もしてきましょう。

nuxt.config.js
export default {
...
modules: [
'@nuxtjs/axios'
],
...
}

axiosはCORS対策もしっかりしてくれているので、このままでは先程作ったウェブアプリのAPIを叩けません。 そこで、proxyします。

nuxt.config.js
export default {
...
modules: [
'@nuxtjs/axios'
],
axios: {
proxy: true
},
proxy: {
'/api': {
target: <ウェブアプリのURL>,
pathRewrite: { '^/api': '' }
}
},
...
}

これで、内部の/apiにaxiosでデータ取得しようとするとCORS対策を迂回してウェブアプリのAPIを叩くことができます。 ちょうど、このURLは信頼できるURLだよ、と登録しているような感覚ですね。

これでウェブアプリのAPIを叩く準備が整ったので、ページを作成していきます。

pages/index.vue
<template>
<div>
<table>
<thead>
<tr>
<th>id</th>
<th>name</th>
<th>age</th>
<th>email</th>
</tr>
</thead>
<tbody>
<tr v-for='user in users' :key='user.id'>
<td>{{ user.id }}</td>
<td>{{ user.name }}</td>
<td>{{ user.age }}</td>
<td>{{ user.email }}</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
export default {
data() {
return {
users: []
}
},
created() {
this.getUsers()
},
methods: {
async getUsers() {
this.users = await this.$axios.$get('/api')
}
}
}
</script>

ちょっと長いですが、templateの方はtablev-for使っているだけなので説明は省略です。

重要なのはscript側ですね。 今回はmethodsgetUsers()async-awaitで記述し、createdで呼び出してます。getUsers()は、axiosを使ってウェブアプリAPIからスプレッドシートのデータを取得して、this.usersにデータを代入してます。

これでページにアクセスしてみると...。

データ取得成功!

スプレッドシートと同じ情報を表示できていますね🎉🎉🎉。

まとめ

今回はスプレッドシートをDB代わりに使えないかなー、ということで以下をやってみました。

  • GASのウェブアプリを使ってスプレッドシートの情報を返却するAPIを作ってみた
  • NuxtアプリでそのAPIを使ってスプレッドシートの情報を表示してみた

それぞれいろいろな参考記事を書いてくださっている方々がいらっしゃったんですが、あわせ技のところで困ったりしたので一連通してやるとこうなるぞという記事を書いてみました。 これですべてが上手くいった...そう思っていたのですが...。

次回、モバイルでもそれ動くのか

お楽しみに😆...😢。

続編を公開しました。

NuxtでスプレッドシートをDB代わりに使うぞ大作戦 Part2 - モバイルだって使いたい! | at-blog
  • 名前:asato
  • 仕事:スクラムマスター
  • 好き:家族、温泉、旅行、謎解き
  • 苦手:はじめまして、あんこ、うなぎ