SpreadsheetをDBとして使うぞ大作戦 on Nuxt
こんにちは。asatoです☀
いま面白いTwitterスペースと出会えるプロダクトspaces.bzを開発しています。
このプロダクトはDBが必要なのですが、できれば簡単でお金のかからない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アプリから叩いてデータを表示していきます。
やることは
です!
まず、@nuxtjs/axiosを導入してきます。
$ yarn add @nuxtjs/axios
モジュールを登録します。
# nuxt.config.js export default { ... modules: [ + '@nuxtjs/axios' ], ... }
次に、serverMiddlewareを作成して経由して叩くことを考えます。
$ yarn add express $ mkdir api $ touch api/index.js
# api/index.js const express = require('express') const axios = require('axios') const app = express() app.get('/', async (req, res) => { const users = await axios.get(<ウェブアプリ(GAS API)のURL>) res.send(users.data) }) module.exports = { path: '/api/', handler: app, }
nuxt.config.js
にも登録しておきましょう。
# nuxt.config.js export default { ... + serverMiddleware: [ + '@/api/' + ], ... }
これで内部の/api/
を経由してGAS APIからデータを取得することができるようになりました。
ウェブアプリの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: [] } }, async fetch() { this.users = await this.$axios.$get('/api') }, } </script>
ちょっと長いですが、template
はtable
とv-for
で表形式に表示しているだけで、script
もaxios
で取得したユーザー情報をthis.users
に格納しているだけです!シンプル!
これでページにアクセスしてみると...
データ取得成功!
スプレッドシートと同じ情報を表示できていますね!!🎉🎉🎉
まとめ
今回はスプレッドシートをDB代わりに使えないかなー、ということで、
をやってみました! それぞれいろいろな参考記事を書いてくださっている方々がいらっしゃったんですが、あわせ技のところで困ったりしたので一連通してやるとこうなるぞという記事を書いてみました。 誰かの参考になれば嬉しいです。
spaces.bzも応援よろしくおねがいします!