山手線を徒歩で一周する人のための記録アプリ「YamaNotes」をリリースしました
はじめに
山手線を徒歩で一周する人のための記録アプリ「YamaNotes」をリリースしました。
この記事では「YamaNotes」の使い方や、開発過程で苦労したことなどをまとめます。
6/14追記:東京の気温が高くなることが予想されています。熱中症予防のため、涼しくなってからの挑戦をおすすめします。
サービスURL www.yamanotes.com
自己紹介
すずかと申します。
昨年4月にFJORD BOOT CAMP(フィヨルドブートキャンプ:以下FBC)に入学して、プログラミング歴は約1年です。以前は高校の国語教員をしていましたが、新しい挑戦をするため退職し、未経験からWebエンジニアを目指しています。
アプリの概要
山手線一周に徒歩で挑戦する人向けの記録アプリです。
各駅の到着時刻や、疲れ具合のメモなどを、簡単に記録することができます。
山手線徒歩一周チャレンジとは?
その名の通り、山手線を徒歩で歩くことです。
正式なデータではありませんが、総歩行距離は約45km、12時間ぐらいかかることが多いようです。RTAとして挑戦している人もいます。
使い方
ログインする
トップ画面からGoogle アカウントでログインします。
初期設定をする
モード(外回り or 内回り)と、出発駅を設定します。
進捗を確認する
現在の進捗が地図上に表示されます。残りの駅数や距離を確認しましょう。
到着する
駅に着いたら、「到着」ボタンを押しましょう。メモを追加したり、Xで進捗をポストすることもできます。
履歴を確認する
到着時刻の編集や、メモの追加を行います。間違えて「到着」ボタンを押した場合は、削除することもできます。
開発に至る経緯
昨年4月に15時間ほどかけて、はじめて山手線を一周しました。
普段ほぼ運動しない私にとっては辛い挑戦でしたが、歩き終わった時の達成感はこれまで感じたことのないものでした。
この挑戦をもっと楽しくするために、「YamaNotes」を作りました。
技術スタック
- バックエンド
- Ruby 3.3.0
- Ruby on Rails 7.1.3.3
- フロントエンド
- Hotwire
- Tailwind CSS
- テスト
- データベース
- CI
- GitHub Actions
- 外部サービス
- Leaflet
- OpenStreetMap
- MapTiler
- Google OAuth
技術選定の理由
「必要な機能を短期間で作ること」「コストを抑えて作ること」を軸に行いました。
短期間で必要な機能を作るため、Rails7とHotwireで実装
FBCのカリキュラムでReactを学習していたため、他のフレームワークを使用することも検討しましたが、数行のコードでSPA風の挙動を実現できる開発コストの低さに惹かれ、Hotwireを採用しました。
本格的な開発に入る前に、猫でもわかるHotwire入門やパーフェクト Ruby on Railsで学習し、想定した機能が問題なく実装できることを確認しました。
実際に開発してみると、Hotwireを使ったのは大正解で、JavaScriptをほとんど書かず素早く実装できることに感動しました。やりたいことを整理した上で、サービスの規模に合わせた技術選定をする重要性を実感しました。
コストを抑えて作るため、APIやデプロイ先を調査
しばらくはサービスを継続したいと考えているため、維持費を抑えることにこだわりました。一部に従量課金制のものがありますが、想定されるアクセス数なら無料で運用できるよう作りました。
特にコストを抑えるために考慮したのは、以下の2つの箇所です。
地図の表示と描画にLeaflet + OpenStreetMapを使用
当初は開発の情報量の多さ・地図の見やすさなどに魅力を感じ、Google Maps APIの使用を検討しました。しかし無料枠がやや少ないと感じたため断念し、無料で使えるものを探した結果、OpenStreetMapで地図を表示してLeafletというライブラリで線や吹き出しを追加することにしました。
加えて、地図タイルをOpenStreetMap標準のものからMapTilerのものに差し替えました。こちらは従量課金制で無料の範囲に収まることをを想定していますが、場合によっては無料のものに戻すつもりです。地図の見やすさとコスト削減を両立できたと思っています。
Render.com + Supabaseでデプロイ
当初はFly.ioにデプロイするつもりでしたが、無料プランが無くなったようなので、Supabaseのデータベースを使ってRender.comにデプロイしました。
Supabaseに触れるのは初めてでしたが、同じFBC生の方が書いたこちらの記事に助けられて、無事デプロイすることができました。
Rails7+Render.com+Supabaseで無料デプロイ - はるまきのブログ
こだわったこと
「YamaNotes」というネーミング
「名前重要」という言葉をよく聞くので、サービス名はこだわりました。
山手線の「Yamanote」と、記録を表す「Note」を組み合わせ、複数形の「YamaNotes」としました。
「山手線一周アプリ」といっても、地図や情報提供・RTAのための時間管理など、色々なアプリが考えられますが、この名前が決まったことにより、山手線一周の「記録」に特化する方向性に決まりました。
地図上に線を引いて、進捗をわかりやすくすること
「記録」に特化したアプリなので、ユーザーは地図を別で用意していることを想定しています。そのため、アプリ上に地図の表示は必須ではなく、下のように路線図に進捗を表示する方法もありました。
しかし、山手線の駅間は最長の区間(大崎〜品川間:約2.0km)と最短の区間(日暮里〜西日暮里間:約0.5km)では、かなりの差があります。路線図の色を変える方式では、駅間の距離の違いを反映できないと考え、地図上に直線を引くことにしました。
進捗をわかりやすくするとともに、地図に直接線が引かれるワクワク感があり、気に入っています。
全ての機能やメソッドに対してテストを書くこと
不具合を見つけてより快適に使ってもらうため、テストコードをもれなく書くよう意識しました。
FBCのカリキュラムではMinitestでテストを書いていましたが、自作サービスではRSpecを使うことにしたので、Everyday Rails - RSpecによるRailsテスト入門を参考に勉強しました。その後、全てのpublicなメソッドや機能について、ひたすらテストを追加しました。
simplecovによると、テストカバレッジは99%のようです。 今後も勉強を続けて、今書けていないテスト(認証周りの異常系など)も追加していきたいです。
苦労したこと
Hotwireが魔法のように見える
「YamaNotes」では、以下の箇所にHotwireを使用しています。
- Turbo Drive:基本的な画面遷移
- Turbo Frames:編集フォームの表示
- Turbo Streams:編集後の更新処理
- Stimulus:地図の表示・線の描画、モーダル・ハンバーガーメニューなど(tailwindcss-stimulus-componentsを使用)
数行のコードを書くだけで動きをつけることができ、非常に便利に感じる一方で、特にTurbo Streamの実装で理解が浅いせいで思うように動かず、苦労しました。 到着履歴画面の削除機能など、まだまだTurboに置き換えたい部分があるので、もっと深く理解できるよう勉強したいです。
カスタムバリデーションを設定すること
到着機能の実装において、「駅の数以上に到着できない」「前後の記録と齟齬がある到着時刻を設定できない」など、色々なバリデーションを設定する必要がありました。
最も苦労したのが、「隣駅以外に到着できないようにする」バリデーションです。内回り・外回りそれぞれで対応する必要があったため、当初はStationテーブルに「外回り時の次の駅ID」と「内回り時の次の駅ID」を持たせる設計にしていました。
ただ、実装時に作りにくさを感じたため、紙に書き出してロジックを考え、次の駅の取得方法を考え直しました。
ロジックを考えた時のメモ
データベースには「外回り時の次の駅ID」のみを持たせ、Stationクラスのnext
メソッドで外回り・内回りに応じて条件分岐することで、要件を満たすバリデーションを設定することができました。
使いやすいデザインにすること
CSSが苦手なのもあり、最低限使えるデザインにするまでが、まず大変でした。一通りデザインを入れた後も、レスポンシブ対応・OGPやFaviconの設定・画像の圧縮やaltの設定・・・・など、使い勝手の良いアプリにするためにやるべき作業が山のようにあり、苦労しました。
自分なりのデザインを入れた後は、FBCのデザイナーさんにレビューをしていただき、修正を繰り返しました。お陰様で、シンプルで使いやすいデザインになったと思っています。
「普通に使えるサービス」のデザインが、如何に考えて作られているかを知ることができ、デザイナーさんへ尊敬の念が湧きました。
今後やりたいこと
複数回記録できるようにする
ファーストリリースでは最低限の機能に絞ったため、現在の実装では、作成できる歩行記録はユーザ一人につき一つだけとなっています。つまり、二周目を歩く際には、一周目の記録を削除して記録する必要があります。
RTAをするために山手線を何周もする人は想定されるため、将来的に複数の歩行記録を作成・閲覧できるようにしたいです。
パフォーマンスの改善
現在は到着ボタンを押した時に、約2秒の時間がかかっています。到着ボタンは何度も押すことになるので、もう少し速くしたいところです。
発行されるクエリを減らすためのリファクタリングや、使っていないインスタンス変数の削除、キャッシュの利用などを行って、若干速くはなりましたが、サクサク動くにはまだ至っていません。到着時にカスタムバリデーションを複数実行していることや、Render.comに東京リージョンがなくシンガポールに設定していることが、要因として考えられます。
今後はパフォーマンスについて勉強するとともに、東京リージョンがあるサービスへの移行も検討しようと思っています。
到着駅に応じたイラストや文言を追加
現在は到着画面が二種類(歩き終わった時用とそれ以外用)だけなのですが、着いた駅や進捗に応じたイラストを表示できると楽しいかなと思っています。例えば、上野駅に着いた時にパンダのイラスト、残り一駅の時に「あとちょっとだから頑張れ!」的なメッセージを出すなどしたいです。
おわりに
作り始めた時は、作りきれるか不安でしたが、どうにかリリースすることができました。
無事リリースできたのは、毎日お世話になったFBCの皆様、あたたかい言葉をかけてくれたRubyコミュニティの皆様、SNSを通じて応援してくださった方々のおかげだと思っています。
YamaNotesは今後も改善を続けるつもりなので、ご意見や感想などをいただけると嬉しいです!