[個人開発・独学]未経験者がHotwireのポートフォリオを作った話【Rails / Hotwire/ TailwindCSS/ Docker / AWS】


<h2>はじめに</h2>

都内の大学に通う(生物学科)３年のチャスと申します。
当記事ではタイトルの通り独学のみでポートフォリオ(以下PF)を作成した過程をご説明します。<br>
制作したアプリケーション(2023/10/2にサーバーを停止)
「<a href="https://karibito.org">~~Karibito~~</a>」<br>
GitHubのURL
<a href="https://github.com/chasumaru/Karibito">GitHub</a>

記事の最後に、お世話になったWeb教材・記事をまとめましたので、参考にしていただければ幸いです。
開発期間は7ヶ月です。大学に通いながら暇なときにコツコツ作りました。また、開発前には学習(迷走)期間が10ヶ月程あり、基本情報技術者試験やRubyの書籍を読んだり、ネット上の簡単なアプリを作ったりしていました。
<h2>PF概要</h2>

<h3>アプリの説明</h3>


TOPページ(冒頭)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2607099/4c65b31d-aa19-26f1-1c41-476be507144e.png)

掲示板一覧
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2607099/1afe08dd-ac87-a28a-f767-1d3487faee0e.png)





Karibitoは狩猟や野生動物に関するSNS掲示板サイトです。
一般的に狩猟では野生動物を狩猟するため、センシティブな画像が散見され、Twitterや個人ブログなど他のSNSではしばしば炎上が起きていました。これについて、僕は次の二つが主要な原因であると考えました。
<ol>
  <li>社会で狩猟に対する理解が浅く、狩猟に関して偏見が持たれやすい風潮であること。</li>
  <li>ネットサーフィンで動物のグロい画像が急に出たら不快であること。</li>
</ol>
そこで、Karibitoではセンシティブな画像が含まれる投稿にカバーをかける機能を実装しました。狩猟の知識がなく、関心が薄い人でも利用できることを開発テーマの一つとしました。


<h3>実装した機能</h3>

|種類|機能名|
---|---
ログイン機能|ユーザー登録、ユーザー編集、ログイン、ログアウト、フォロー、ユーザー一覧、ユーザーの投稿一覧、退会(物理削除)
日記投稿機能|投稿、編集、削除、画像複数枚登録
日記コメント機能|日記に対するコメント投稿、リプライコメント、編集、削除
日記いいね機能|日記のいいね、いいねしたユーザー一覧
掲示板機能|掲示板の作成、匿名で掲示板を作成、編集、削除、画像登録
掲示板コメント機能|掲示板に対するコメント投稿、匿名で投稿、編集、削除
タグ管理機能|日記・掲示板・ユーザーにタグを登録可能、タグをタップするとタグによる絞り込み検索が可能、タグ一覧ページではタグとその件数を表示
検索機能|各コンテンツ毎のインスタントサーチ(部分一致)
通知機能|ツイートへのいいね・コメント、掲示板にコメント、他ユーザーからフォローで通知
管理者機能|管理者権限を設定、全てのModelオブジェクトに対するCRUD操作
お問い合わせ|Google Form

<h2>利用した技術</h2>
<h3>各種バージョン</h3>
<ul><li>Ruby: 3.1.2
<li>Rails: 7.0.4
<li>TailwindCSS: 3.0.24
<li>Turbo-rails: 1.3.2
<li>Stimulus-rails: 1.1.1
<li>Docker: 19.03.1
<li>docker-compose: 1.24.1

<h3>フロントエンド</h3>

|名称|説明|
---|---
Turbo|画面遷移を高速化するフレームワーク
Stimulus.js|JSフレームワーク
TailwindCSS|CSSフレームワーク

<ul><li>フレンドリーフォワーディングを設定
<li>TailwindCSSによるレスポンシブデザイン。メディアクエリを適切に設定し、必要に応じてカスタムクラスの作成や、プラグインを利用した。
<li>コンテンツの一覧ページではFlexBoxではなく、Gridを採用した。
<li>Hotwireの実装指針として、Turbo(Drive>Frame>Stream)で対応できない場合にStimulusを実装した。
<li>Turbo Driveは全ページ遷移で有効化し、遷移を自然にするためにanimate-fade-inカスタムクラスを作成した。
<li>Turbo Frameはコメントのeditアクションやインスタントサーチのコンテンツ一覧などに利用した。
<li>Turbo Streamはコメントのcreate,update,destoyアクションや、いいね、フォロー、通知機能などに利用した。
<li>stimulusはサイドバー、画像カバー、プレビュー機能など全てのJS動作をcontrollerとして記述しました。
</ul>

<strong>所感</strong>
Turbo Frame内ではTurbo Streamを設定してもTurbo Frameリクエストになるというルールのせいで、コメントのCRUD実装時に苦労しました。また、<a href='https://github.com/excid3/tailwindcss-stimulus-components'>便利なstimulusコンポーネント</a>は学習のために、極力利用を避けました。


<h3>バックエンド</h3>

|名称|説明|
---|---
Nginx|Webサーバー
Puma|APサーバー
Rails|Webフレームワーク
MySQL|RDBMS

<ul>
<li>NginxとPumaはソケット通信で連携させています。
<li>画像データはActiveStorage経由でS3バケットに保存。
<li>その他のデータはRDSに保存。
<li>トップページでは直近2週間で注目のあるコンテンツをランキング順に表示。
<li>投稿される画像は10MB以下、枚数も制限した。
</ul>

<h3>テストコード</h3>

|名称|説明|
---|---
Rspec| バックエンドテスト(Validation,Associationのみ)<br>フロントエンドテスト: (認証前後のページ遷移のみ)<br>計176examples


<h3>インフラ</h3>

|名称|説明|
---|---
RDS| 本番用DB（MySQL）
Docker, Docker-compose| コンテナ環境
Git| バージョン管理ツール
GitHub| ソースコード管理

<ul>
<li>ローカル開発環境からデプロイまで一貫してDockerを利用。
<li>ELBを通すことで常時SSL通信化。
<li>環境変数はローカルから本番環境にgitignoreに記載されたファイルを渡した。
<li>(デプロイ経路)ローカルからGitHubへpush→EC2にSSH接続→GitHubからpull。

<h3>インフラ構成</h3>

![インフラ構成図(枠線).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2607099/4ecb7186-6232-9e03-c203-49ed6cbff250.png)

- 基本方針はAWS無料枠の利用。スケールに変化がなければ、ランニングコストは月1＄程度(Route53のみ)。
- RDSにはMySQL8.0を利用。
- S3には画像データを保存。
- ELBを利用するためにAvairability Zoneの異なるpublic subnetを用意した。

<strong>所感</strong>
開発当時は無料であったため、Herokuへのデプロイも考えました。しかし、日本リージョンがなく、レイテンシーがTurboを利用する上で無視できない大きさであることを知ったため、やめた。(<a href='https://zenn.dev/shita1112/books/cat-hotwire-turbo/viewer/tutorial-1#%E3%83%81%E3%83%A5%E3%83%BC%E3%83%88%E3%83%AA%E3%82%A2%E3%83%AB%E5%85%A8%E4%BD%93%E3%81%AE%E8%AA%AC%E6%98%8E'>参照元</a>)
<h3>ER図</h3>

![Karibitono.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2607099/c3163da1-ac96-09a4-3374-409b489d6aca.png)


<h3>主要gem一覧</h3>
<ul>
 <li>sprockets-rails　　　 ...アセットパイプライン
 <li>importmap-rails   　  　...ESモジュールをCDN経由で読み込む
 <li>cssbudling-rails 　  　 ...Tailwind CLI のインストール
 <li>turbo-rails 　 　  　 　...Hotwire
 <li>stimulus-rails 　  　 　...Hotwire
 <li>devise　　　　　　　...ユーザー認証
 <li>devise-i18n 　 　　 　...ユーザー認証の日本語化
 <li>rubocop-rails 　  　 　 ...静的解析ツール
 <li>Rspec　　　　　 　　...テストフレームワーク

 <li>ransack　　　　　 　 ...検索, ソート
 <li>pagy　　　　 　 　 　...ページネーション
 <li>acts-as-taggable-on　...タグ
 <li>mini_magick　　 　 　...画像処理
 <li>cancancan　　　　 　 ...管理者権限
 <li>rails_admin　　　　　 ...管理者権限
 <li>sassc-rails　　　 　 　 ...(rails_adminとの依存関係)
</ul>

開発時、アセットパイプラインにpropshaftを利用していたが、rails_admin(sassc-rails依存)の導入により、ローカルで不具合が生じ、本番環境でコンテナ起動時にエラーが発生したため、sprockets-railsに差し替えた。

<h3

<h2>制作過程</h2>
<strong>筆者について</strong>

僕は大学に入学するまでパソコンをほとんど触ったことがなく、プログラミングのプの字も知りませんでした。入学当初、情報の授業(Excel処理)では下のクラスとなり、タッチタイピングすらできませんでした。しかし、オンライン授業の影響もあり、パソコンに触れる機会が増えました。最初は、Excelのショートカットキーやオートフィルといった便利な機能に触れました。このとき、PC知識が効率化に直結していることに気づき、知識の吸収に貪欲な気持ちが生まれ、アプリ開発の意欲に結びつきました。また、私の祖父や友人など狩猟免許を持つ人と関わる中で、狩猟とSNSをアイデアとして取り入れました。そして、冒頭のアプリの説明で述べた社会問題を元に、狩猟が身近に感じられるような掲示板を構想しました。<br>


<h3>開発所感</h3>

<strong>Rails7を採用した背景</strong><br>
主要ブラウザがES6に対応したことにより、フロントエンド(アセットパイプライン)周辺の新しい技術が出現しました。開発直前、Qiitaやプログラミングスクールのサンプルなどで見られるような、RailsをBackend APIとして利用し、フロントエンドをVue.jsで開発するための勉強をしていました。<br>
しかし、DHH氏のRails7の記事(<a href="https://world.hey.com/dhh/modern-web-apps-without-javascript-bundling-or-transpiling-a20f2755">Modern web apps without JavaScript bundling or transpiling</a>)を読んだことで、Rails7のアセットパイプラインやHotwireが現在のブラウザにマッチしていると思いました。そこで、好奇心と不安を胸に学習を始めました。後には引けないので必死に勉強しました。

<strong>インフラについて</strong>
時間がかかったこともあり、デプロイを急ぎました。そのため、CircleCIなどのCI/CDツールや、Terraformによるインフラのコード管理は、暇な時や必要性を感じた場合に勉強したいと思います。

<h3>大変参考にさせていただいた記事・資料</h3>

<ul>
<li><a href='https://railstutorial.jp/'>Railsチュートリアル</a><br>
原点にして頂点の参考書だと思います。僕が唯一課金した教材です。2度挫折済み。</li><br>
<li><a href='https://www.amazon.co.jp/Amazon-Web-Services-%E5%9F%BA%E7%A4%8E%E3%81%8B%E3%82%89%E3%81%AE%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF-%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E6%A7%8B%E7%AF%89/dp/4822262960'</li>AWS基礎からのネットワーク&サーバー構築</a><br>
デプロイ前に図書館で借りて読みました。</li><br>
<li><a href="https://zenn.dev/shita1112/books/cat-hotwire-turbo">猫でもわかるHotwire入門 Turbo編</a><br>
最も分かりやすく体系化されたHotwireの日本語の入門書。日本語の記事が少なく、あっても断片的な情報の記事が多い中、最高でした。Turbo, Stimulusは基本の理解に時間がかかったので重宝しました。実際にサンプルアプリを作って理解が深まりました。</li><br>

<li><a href='https://www.wantedly.com/companies/wantedly/post_articles/354873'>Rails 7.0でアセットパイプラインはどう変わるか</a><br>利用するJS,CSSフレームワークに応じて、アセットパイプラインの選択肢を考えるのに役立ちました。</li><br>

<li><a href='https://tailwindcss.com/docs/installation'>TailwindCSS Docs</a><br>TailwindCSSの公式ドキュメント。全てのutilityクラスが具体的なサンプルと共に整理されており、飽きるほど調べた。</li><br>

<li><a href='https://qiita.com/jnchito/items/5c41a7031404c313da1f'>Rails 7.0 + Ruby 3.1でゼロからアプリを作ってみたときにハマったところあれこれ</a><br>Turbo何それ？状態のとき、最初に読みました。</li><br>

<li><a href='https://blog.corsego.com/'>SupeRails by Yaroslav Shmarov</a><br>
ウクライナ出身のrailsエンジニアの方のブログ。Rails周辺、特にHotwireの実践的なサンプルコードを解説されている。とても勉強になった。</li><br>

<li><a href='https://turbo.hotwired.dev/handbook/introduction'>Turbo Handbook</a> ...Turboの公式本。全てに目を通し、適宜参照した。</li>
<li><a href='https://stimulus.hotwired.dev/handbook/introduction'>Stimulus Handbook</a> ...Stimulusの公式本。全てに目を通し、適宜参照した。</li>


<h3>開発時の自己ルーティン</h3>
<ul><li>実装する機能の関連記事を集め、正確な情報を抽出する。
　<li> 繰り返し現れる用語は必ず検索して調べ、最低でも概要は理解する。
　<li> Rails6 の環境との差分理解を意識する。(Rails6の情報は多いため)
　<li> 必要に応じて思考を紙に書き出して整理・体系化する。
  <li> 思ったことやアイデアは全て<a href='https://www.giuspen.com/cherrytree/'>cherrytree</a>にメモる。
  <li>エラーやその後の対応の過程を適宜、cherrytreeにメモる。
</ul>

<h3>終わりに</h3>
説明に不備などございましたら、コメント、Twiiterの方からご指摘ください。
この記事がどなたかの参考になれば幸いです。