概要
- QRnoteは誰でも使えることが特徴のオンライン予約表です
- Rails + React + Dockerで開発し、Elastic Beanstalkで公開しています
- ソースをGitHubで公開していますので、記事内のライブラリの紹介とあわせてご参照ください!
まず使いたい!
いますぐ試したい
ローカルで動かしたい
- https://github.com/junara/qrnote をクローン。
- Dockerで開発していますので、下記のcommandでを実行して起動して下さい。 https://localhost:3000 にQRnoteが起ち上がります。
docker-compose build
docker-compose run web yarn install
docker-compose run web rails db:create
docker-compose run web rails db:migrate
docker-compose up
- 終わるときは、
docker-compose down
自己紹介
エンジニア歴
- 1977年生まれの40歳。その他こちらと重なるので省略
- 2016年6月からWebエンジニアとして働き始めました
- 普段からRails, Reactのお仕事やっています
QRnoteの紹介
- 無料のオンライン予約表です
- 2日後まで予約できます
開発期間
- 2017年11月から4ヶ月ぐらい
特徴
- 誰でもすぐ使える
開発のきっかけ
会社勤めしていると社内共通の備品ってありますよね。それらの使用頻度が増えたときに登場する紙の予約表。(備品の横に置かれたEXCELでつくって印刷した紙のカレンダーとか)
2018年なのに未だ手書きって・・・・と感じていたのでつくりました。
備品予約表の問題は?
備品予約を紙のカレンダーで管理するとやはりめんどい
- 予約参照する場合→備品のところまで歩いて行って目視で確認→めんどい
- 予約する場合→紙のカレンダーに手書きで名前を書き込む→めんどい
備品予約表をgoogle スプレッドシートとかExcelで作ってみるけどめんどい
- google driveにおいてアクセス→PCからアクセスできる→カレンダー表作るのめんどい
備品予約表をgoogle calendarとかoutlookで作ってみるけどめんどい
- google calendarとかoutlookカレンダーを共有する→カレンダーにアクセスできるけどアクセス権考えるのめんどい
めんどくない予約表を作ろう
- さくっと公開、誰でもすぐ使えるオンライン予約表を作ればめんどいが世の中からへってうれしいかも
仕様
無駄な機能は省こう
調整さんいいサービスですよね。無駄な機能がないので使いやすい。
これを手本に、まず実装しない機能を決めました。
- アクセス権制御(承認)は実装しない←知り合い同士なら性善説でいいじゃん
- ログインログアウト機能(認証)は実装しない←そこまで秘密にするほどの情報じゃないならそこそこでいいじゃん
- ユーザーの排他制御は実装しない←予約状況がみえれば、適宜判断すればいいじゃん
- 分単位で予約機能は実装しない←分刻みの稼働してないじゃん
実装する機能
- 新規予約表作成&固有UUID付与
- 認証:予約表固有UUIDを知っているか否か
- 承認:なし(固有UUIDを知っているユーザーは全機能使える)
- 予約CRUD
- 予約作成:予約は名前を書くだけにする。予約時間帯は30分刻み固定。
- 予約表示:当日含む3日間。
- 予約更新:実装しない
- 予約削除:実装
コード解説
構成概要
RailsでAPIつくってReactで表示するシンプルな構成です。
- Rails: > 5.1
- React: > 16
使ったライブラリと説明
Rails
全般的には、こちらの記事を参考にしました。
API
APIの作成はjbuilderです。ざっくりつくるのに、自由度高くAPIが設計できるところが好きなので選択しました。
他の候補は、active_model_serializersとfast_jsonapi。これは、次回以降のアプリでやります。
特に、fast_jsonapiはactive_model_serializersよりも25–40x speed!なんて書かれているので次回以降のアプリで積極的使いたいです。
- 参考にしたサイト
メタタグ
定番のmeta-tags。それ以外知らない。
- 参考にしたサイト
定数管理
configつかっています。dot envよりもymlで階層的に管理できるので好み。
- 参考にしたサイト
サーバー監視
認証機能がないので、過剰なリクエスト(特にpost)をはじくため、rack-attackを導入しています。
- 参考にしたサイト
あと、念のため、impressionistでIPをDBに記録しています。ただ、これは不要だったかも。
例外処理
特別なライブラリはないです。
こちらの記事を参考にしました。
他にもあったのですがリンクメモしていない。すみません。
React
この記事を書き始めたときに、このQiitaの記事「React Redux の SPA を運用して得られた知見と実装例、開発フローもあるよ!」が出ました。素晴らしい記事です。すごいわかりやすいので、ぜひみんな読むべき。
0からReactでSPAを書いた身として、この記事が一番まとまっている思いました。個人的には、読後、HOCが使いたくなりました。HOCでダイアログDryに書き直したい。
いい記事公開の直後なので、お恥ずかしいですが、react の SPAの一例として捉えて読んでください。
state管理
react-redux。王道。バケツリレーしたくない。
モデルをimmutableのrecordで作りました。recordを使うと、railsのmodelっぽくstateを扱えるコードを書くつらみが、かなりなくなります。強くオススメ。
ミドルウェアはredux-saga。他の候補は、redux-thunk。redux-thunkは軽く導入できるので、最初redux-thunkを作っていました。しかし、書き続けるとreducerが肥大して行く感じがしたので、早々に、redux-sagaに変更しました。
redux-sagaはとっつきにくいです。使い方を理解するまで、1週間ぐらいかかりました。でも、苦労する甲斐はあるとおもう。非同期処理をキレイに分離できます。
- 参考にしたサイト
ページ遷移
react-router。これも王道。公式のドキュメントが豊富なのでそれを読めば使える。
V4で大きく変更があったみたいなので、新しいドキュメントを参照すること推奨。
HTTPクライアント
axios。他の選択肢は、superagentとfetch。特に、fetchは公式のAPIなので迷いました。しかし、最終的にはドキュメントの豊富さからaxiosを採用しました。
- 参考にしたサイト
CSSフレームワーク
material-ui v1.0.0-beta。マテリアルデザインにすることは決めていました。その中で、reactでマテリアルデザインを実現するフレームワークでもっともメジャーだった、material-uiを選択しました。
他のフレームワーク候補はこちら。
material-ui、かなりオススメです。ドキュメントが豊富なので、それをそのまま使うだけでどんどん機能が実装できます。また、デモコードを読んだり、material-ui自身のソースを読むととても勉強になります。今回のアプリのソースは、8割以上material-ui(とドキュメント)のおかげ。
-
注意点
- materia-uiは現在ベータ版。breaking changeが高頻度で入ってくるので、安易なyarn upgradeはしない方がいい
- 実際この記事を書く前にbreaking changeがあったので、急遽コードの修正をした
- material-uiの1.0 betaと0.xは全く仕様が異なる。古い記事は参考にしづらい。
- (material-uiの本質じゃないけど)CSS in JSは便利。だけど、とっつきづらい。
- materia-uiは現在ベータ版。breaking changeが高頻度で入ってくるので、安易なyarn upgradeはしない方がいい
-
参考にしたサイト
日付処理
date-fns。他の候補はmoment。momentがメジャーで機能が豊富ですが、date-fnsを選択。
date-fnsにした理由は、immutableだから。ruby(rails)のTimeとかActiveRecordと同じ感じで使えてき気持ち良いです。
- 参考にしたサイト
- https://date-fns.org/ 公式だけどほぼこれでOK
- https://www.webprofessional.jp/date-fns-javascript-date-library/ これ読んでdate-fns導入を決めた
その他
機能の根幹ではないけど、その他使ったライブラリを紹介します。
QRコード表示
最近、電脳コイル見てるというのもあるのですが、グラス型デバイスを調べています。日本のQDレーザーとか、Appleが開発中との噂もあります。グラス型のデバイスが日常にやってくるのも遠くなさそう。
今回、各備品には固有のQRコード画像をつけました。ユーザーがQRコードをテプラなどで印刷したシールを備品に貼って、スマホのカメラでスキャンする未来を期待してます。電脳コイルの世界にちょっとでも近づきたいと思って。
- 使い方のイメージの参考
- 実装に使ったライブラリ
- react-qr-svg SVG形式で、QRコードをで出力できるのがいい。
- rqrcode サーバー側でQRコード画像生成
コピペ
URLをクリップボードにコピーできるボタンを作成するために使用。
画面のスクロール制御
任意の場所(refsで指定)に移動するために使用。
シェア
シェアボタン
-
react-share facebookなど定番のシェアボタンの作成に使用した。
[![https://gyazo.com/4e0c0a3db2c2919858556ffed5da508c](https://i.gyazo.com/4e0c0a3db2c2919858556ffed5da508c.png)](https://gyazo.com/4e0c0a3db2c2919858556ffed5da508c)
-
list-it 予約状況を下記の様なテキスト形式の表を出力するために使用した。
現時点の予約者リスト
02/19(月) 午後03:00-03:30 平松光叶
02/19(月) 午後03:00-03:30 篠原武瑠
02/21(水) 午後02:00-02:30 広瀬一平
02/21(水) 午後05:30-06:00 及川萌風
iCalカレンダ出力
iCalendar形式で出力するために使用した。railsの定番。
アニメーション
UXを良くするために導入。
- react-countup 予約者数をカウントアップしてアニメーションするために使用した。
- velocity-react 予約者のchipsをふわーっと表示するために使った。囲めばいいだけなので、使いやすい。
- react-loading fetching中を示すためのアニメーション
メモ機能
メモ機能の実装のために導入。サーバーサイドでやるのはコストが高いので、クライアントでmarkdown変換してもらうことにした。
- react-markdown メモを残す機能を実装するために使用。
デモ用のランダムデータ作成
デモデータを出力するためのランダムデータ用に導入。日本語のデモデータってあまり種類ないですよね。
deploy
AWS ElasticBeansTalk
Herokuとどちらにするか迷ったけど、HTTPS化するのが楽ちんなので、AWSにしました。
-
参考にしたサイト
- http://blog.wackwack.net/entry/2017/02/07/223956 非常に丁寧に説明されています。HTTPS化の所とか、ここまで優しく手順が示されているのはすごい。
-
関連の拙記事
- https://qiita.com/junara/items/ae09c94da5223c9c3aff AWSの導入まで
- https://qiita.com/junara/items/8eb501b855697fedc42e Encrypted Secretの使い方
- https://qiita.com/junara/items/62b0e11f71111ef8e4ce ドメイン取得と反映
感想
実装しない機能を決めるのすごい大事。デザインも楽になるし、使いやすくなるし、リリースも早くできるのでいいことづくしです。特に、個人開発だとだらだらしちゃうので、リリースが早くできるのは大きな利点です。
また、すべて公開(今回であれば、GitHubソース公開とQiitaへの記事投稿)をゴールにしたのもよかったです。Outputする過程で知識が定着することを実感できたので楽しいです。