Rails
React
Rails5

RailsとReactでオンライン予約表QRnoteを作って公開した話

概要

  • QRnoteは誰でも使えることが特徴のオンライン予約表です
  • Rails + React + Dockerで開発し、Elastic Beanstalkで公開しています
  • ソースをGitHubで公開していますので、記事内のライブラリの紹介とあわせてご参照ください!

まず使いたい!

いますぐ試したい

ローカルで動かしたい

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日後まで予約できます

https://gyazo.com/4c9a2654bf5c809cc74689b34de28d55

開発期間

  • 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_serializersfast_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。他の選択肢は、superagentfetch。特に、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は便利。だけど、とっつきづらい。
  • 参考にしたサイト

日付処理

date-fns。他の候補はmoment。momentがメジャーで機能が豊富ですが、date-fnsを選択。

date-fnsにした理由は、immutableだから。ruby(rails)のTimeとかActiveRecordと同じ感じで使えてき気持ち良いです。

その他

機能の根幹ではないけど、その他使ったライブラリを紹介します。

QRコード表示

最近、電脳コイル見てるというのもあるのですが、グラス型デバイスを調べています。日本のQDレーザーとか、Appleが開発中との噂もあります。グラス型のデバイスが日常にやってくるのも遠くなさそう。

今回、各備品には固有のQRコード画像をつけました。ユーザーがQRコードをテプラなどで印刷したシールを備品に貼って、スマホのカメラでスキャンする未来を期待してます。電脳コイルの世界にちょっとでも近づきたいと思って。

https://gyazo.com/f4c3d38750d01039af30300469227b78

コピペ

URLをクリップボードにコピーできるボタンを作成するために使用。

https://gyazo.com/938dd3719cbd6b6008488c4a564b420d

画面のスクロール制御

任意の場所(refsで指定)に移動するために使用。

シェア

シェアボタン

  • react-share facebookなど定番のシェアボタンの作成に使用した。

    https://gyazo.com/4e0c0a3db2c2919858556ffed5da508c

  • list-it 予約状況を下記の様なテキスト形式の表を出力するために使用した。

example_mail.txt
現時点の予約者リスト

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の定番。

https://gyazo.com/cc92dd79eb8125a624e794d6445cb76b

アニメーション

UXを良くするために導入。

https://gyazo.com/075af2da64aeb4e82058503801477a61

  • react-countup 予約者数をカウントアップしてアニメーションするために使用した。
  • velocity-react 予約者のchipsをふわーっと表示するために使った。囲めばいいだけなので、使いやすい。
  • react-loading fetching中を示すためのアニメーション

メモ機能

メモ機能の実装のために導入。サーバーサイドでやるのはコストが高いので、クライアントでmarkdown変換してもらうことにした。

  • react-markdown メモを残す機能を実装するために使用。

デモ用のランダムデータ作成

デモデータを出力するためのランダムデータ用に導入。日本語のデモデータってあまり種類ないですよね。

https://gyazo.com/01b61f5ddee925a430476919ac8b9924

  • fakergimei 日本語姓名のランダムデータ作成に使用。

deploy

AWS ElasticBeansTalk

Herokuとどちらにするか迷ったけど、HTTPS化するのが楽ちんなので、AWSにしました。

感想

実装しない機能を決めるのすごい大事。デザインも楽になるし、使いやすくなるし、リリースも早くできるのでいいことづくしです。特に、個人開発だとだらだらしちゃうので、リリースが早くできるのは大きな利点です。

また、すべて公開(今回であれば、GitHubソース公開とQiitaへの記事投稿)をゴールにしたのもよかったです。Outputする過程で知識が定着することを実感できたので楽しいです。