NuxtでスプレッドシートをDB代わりに使うぞ大作戦
こんにちは。@asatoです☀
スプレッドシートをデータベースとして使いたい!
いま話題のTwitterスペースと出会えるプロダクトspaces.bzを開発しています。
GASでTwitter APIをたたいてスプレッドシートに記録するプロトタイプからはじめました。
プロトタイプのあと、「せっかくだからこのスプレッドシートをそのままDBみたいに使えないかなー」と思い、Nuxt + Spreadsheet構成でプロダクトを開発してみたので、体験記をまとめたいと思います!
この記事でやること
スプレッドシートからデータを取得して表示するNuxtアプリを作ります。
サンプルのスプレッドシートは以下のようなイメージ。
id | name | age | |
---|---|---|---|
1 | Test A | 20 | test_a@sample.com |
2 | Test B | 30 | test_b@sample.com |
3 | Test C | 40 | test_c@sample.com |
スプレッドシートをJSONで返却するGASを作成
まずはスプレッドシートの情報を取得するAPIみたいなものを作っていきます。
GASでプログラムを組んでWebアプリとして公開する、をしますが、GASの方からやっていきます。
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リクエストが来たときに動く関数です。
今回のコードではdoGet
関数が動き出したらgetUsers
関数を呼び出してスプレッドシートの中身をJSONに整形し、
return ContentService
.createTextOutput(JSON.stringify(users))
.setMimeType(ContentService.MimeType.JSON)
で、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
に代入しています。これによって、keys
、rows
は以下のようになります。
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
の要素を一つずつ取り出し、
処理2
でobject[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サイトはGASのエディターの上部にある「デプロイ」ボタンから行います。
「デプロイ」>「新しいデプロイ」を選択して...
「種類の選択」>「ウェブアプリ」を選択して...
「新しい説明文」にわかりやすい名前(productionとかtestとか)、「次のユーザーとして実行」に「自分」、「アクセスできるユーザー」に「全員」を設定し、「デプロイ」を選択して...
(必要な場合は)「アクセスを承認」を選択して...
「Google認証」して...
「Advanced」を選択して、「<プロジェクト名>(unsafe)」を選択して...
「Allow」して...
完了!!🎉
「ウェブアプリ」の方に書いてあるURLがAPI(サイトとしても)公開しているURLになります。ちょっとcurlしてみましょう。
$ 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
を導入してきます。
$ yarn add @nuxtjs/axios
nuxt.config.js
でモジュール登録もしてきましょう。
export default {
...
modules: [
+ '@nuxtjs/axios'
],
...
}
axiosはCORS対策もしっかりしてくれているので、このままでは先程作ったウェブアプリのAPIを叩けません。
そこで、proxyします。
export default {
...
modules: [
'@nuxtjs/axios'
],
+ axios: {
+ proxy: true
+ },
+ proxy: {
+ '/api': {
+ target: <ウェブアプリのURL>,
+ pathRewrite: { '^/api': '' }
+ }
+ },
...
}
これで、内部の/api
にaxiosでデータ取得しようとするとCORS対策を迂回してウェブアプリのAPIを叩くことができます。
ちょうど、このURLは信頼できるURLだよ、と登録しているような感覚ですね。
これでウェブアプリのAPIを叩く準備が整ったので、ページを作成していきます。
<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
の方はtable
とv-for
使っているだけなので説明は省略です。
重要なのはscript
側ですね。
今回はmethods
でgetUsers()
をasync-await
で記述し、created
で呼び出してます。getUsers()
は、axios
を使ってウェブアプリAPIからスプレッドシートのデータを取得して、this.users
にデータを代入してます。
これでページにアクセスしてみると...
スプレッドシートと同じ情報を表示できていますね!!🎉🎉🎉
まとめ
今回はスプレッドシートをDB代わりに使えないかなー、ということで、
- GASのウェブアプリを使ってスプレッドシートの情報を返却するAPIを作ってみた
- NuxtアプリでそのAPIを使ってスプレッドシートの情報を表示してみた
をやってみました!
それぞれいろいろな参考記事を書いてくださっている方々がいらっしゃったんですが、あわせ技のところで困ったりしたので一連通してやるとこうなるぞという記事を書いてみました。
これですべてが上手くいった...そう思っていたのですが...
次回!モバイルでもそれ動くの?
お楽しみに!😆...😢
spaces.bzも応援よろしくおねがいします!
続編を公開しました!
Discussion