【Rails7】Rails7 Hotwire × TailwindCSS SPA風ポートフォリオor個人開発アプリの下地を作ろう！(環境構築・投稿機能作成まで)


## はじめに

未経験からエンジニアに転職して、２ヶ月ほど経つエンジニアです。
業務にあたりながらも、小規模なアプリを作って楽しんでいます。
その中で、RailsにHotwireを使用して作成したアプリが、
+ 未経験からエンジニアに転職するためのポートフォリオ
+ 個人開発のアプリ

に向いているのではないかなと思いました。

## なぜポートフォリオ or 個人開発に向いているか
**エンジニア歴２ヶ月の弱弱エンジニアの意見なので、あくまで参考程度に考えていただきたいです。**

**結論**
**フロントエンドのコードをほとんど書かなくても、SPA（シングルページアプリケーション）風のサービスを比較的簡単に作成できるからです。**

比較的というのは、VueやReactなどのフロントエンドのフレームワークを使用するより、という意味合いです。

自分自身、エンジニアに転職する時に完全SPAのポートフォリオを作成しました。
転職活動の際には、
**未経験でここまで作りきることができるのはすごい**
というような評価をもらうことが多くありました。（あくまで未経験にしては、ということです。）

Rails×React(Typescript)で作成したアプリをAWSで公開する
という感じで作ったので、かなり大変でした。
詳細はこちら↓
[【未経験】【エンジニア転職】Rails, React, AWS, Docker を使用した SPA サービス作成までの独学方法](https://qiita.com/AGO523/items/22dc24407540d2837bb0)

バックエンドのことも大して知らない未経験の初学者がフロントエンドにも手を出すと、膨大な時間がかかります。
転職用のポートフォリオとして、RailsのHotwireを駆使したSPA風のアプリを作れば、ライバルと差別化できるのではないかなと思います。

こういった背景から、
**初学者にRails７でHotwireを使用したアプリの下地を提供したいと思いました。**

## 想定している読者
+ 転職用のポートフォリオを作成する方
+ エンジニア転職に向けて学習している方
+ 個人開発のアプリを作ろうと思っている方
+ Rails７でHotwireを体験してみたい方

## 作成するアプリの概要
Rails 7.0.3
Ruby 2.7.6
デザインは TailwindCSS を使用してサクッといい感じにしていきます。

今回作成するのは、投稿機能をメインとしたアプリです。
SNS系やブログ系、イベント系など派生できる下地として考えています。
大抵のアプリに投稿する機能が必要になるかなと考え、汎用性を考慮しての選択です。

なお、作成するにあたり様々な情報を参考にしておりますが、とりわけ↓の記事を大いに参考にさせていただいております。
[参考：猫でもわかるHotwire入門 Turbo編](https://zenn.dev/shita1112/books/cat-hotwire-turbo)


#### 機能
認証（ユーザー登録）機能
投稿機能
　削除機能
　編集機能
　一覧機能
　詳細機能
　検索機能
　ソート（並べ替え）機能
　タグ機能
　ページネーション機能

#### 拡張性
前述の通り、ポートフォリオや個人開発の下地を想定しています。
上記の機能があれば、様々なアプリに拡張していけると考えています。
コメント機能やイイね機能などを追加してSNS色を強めていっても良いですし、
そのままブログ系のサービスにしても良いです。
ご自身のアイデアと融合させていって欲しいです。

## 環境構築
それでは、開発していきます。
環境構築に関しては以下の記事を大いに参考にさせていただきました。
[参考：Rails7を構築してみる](https://qiita.com/tikaranimaru/items/70f87b1fe4b1e7166348)
~~~ 
$ mkdir Rails7-sample
$ cd Rails7-sample

# rubyのバージョンが2.7以上か確認する
$ ruby -v
ruby 2.7.6

$ touch Gemfile
~~~

Ruby のバージョン管理は以下を参考にしました。
[参考：rbenvでrubyのバージョンを管理する](https://qiita.com/hujuu/items/3d600f2b2384c145ad12)

~~~ruby:Gemfile
source "https://rubygems.org"
ruby "2.7.6"
gem "rails", "~> 7.0.3"
~~~

~~~
$ bundle install

$ rails -v
Rails 7.0.3
~~~

~~~
$ rails new . --css=tailwind --skip-jbuilder --skip-action-mailbox --skip-action-mailer --skip-test
# Gemfile は上書きでOKなので y を入力
/Gemfile? (enter "h" for help) [Ynaqdhm] y

$ rails db:create
$ rails db:migrate
~~~
rails new のオプションは以下となっています。（後からでも変更して導入できます）
- --css=tailwind: CSSフレームワークにTailwindを利用
- --skip-jbuilder: jbuilderを導入しないオプション
- --skip-action-mailbox: action-mailboxを導入しないオプション
- --skip-action-mailer: action-mailerを導入しないオプション
- --skip-test: testを導入しないオプション

ここまできたら下記コマンドでrails を立ち上げてみましょう。画像のようなトップページが表示されるかと思います。
~~~
$ bin/dev
~~~
![スクリーンショット 2022-06-06 7.50.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916052/b362f63e-67a3-1460-ecf6-b55acedbd6ae.png)

rails s ではなく bin/dev でサーバーを起動することについては、以下の記事などを参考にしてください。
[参考：Rails 7.0 + Ruby 3.1でゼロからアプリを作ってみたときにハマったところあれこれ](https://qiita.com/jnchito/items/5c41a7031404c313da1f#bindev-%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%A7%E3%82%B5%E3%83%BC%E3%83%90%E3%82%92%E8%B5%B7%E5%8B%95%E3%81%99%E3%82%8B)

## TailwindCSSのUIフレームワークを導入
さて、次はTailwindCSSのUIフレームワークを導入していきます。
ここでも以下を参考にさせていただいております。
[参考：Rails7を構築してみる](https://qiita.com/tikaranimaru/items/70f87b1fe4b1e7166348)
~~~
# daisyuiをインストールする
$ yarn add daisyui
OR
$ npm i daisyui
~~~
https://daisyui.com/

daisyUIを使用するよう設定します。（すぐにできます。）
~~~config/tailwind.config.js
const defaultTheme = require('tailwindcss/defaultTheme')

module.exports = {
  :
  :
  plugins: [
    require('@tailwindcss/forms'),
    require('@tailwindcss/aspect-ratio'),
    require('@tailwindcss/typography'),
    require('daisyui'),    // ← 追加
  ],
}
~~~
https://daisyui.com/docs/themes/

↑からご自身の作りたいアプリに合うテーマを選びます。
今回はサンプルとして、明るくて柔らかい印象のあるテーマを選択します。
~~~html:app/views/layouts/application.html.erb
<html data-theme="pastel" >  // data-theme="pastel" でテーマを選ぶ
  <head>
    :
  </head>

  <body>
    :   
  </body>
</html>
~~~
これで設定が完了です。

## 投稿機能を作成する
~~~
$ rails g scaffold Post title:text            
$ rails db:migrate
~~~
http://localhost:3000/posts　
にアクセスします。
tailwind が効いているのが確認できるかと思います。
scaffoldで作成したPostに自動でやってくれるので、すごく簡単ですね！
![スクリーンショット 2022-06-17 8.25.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916052/f7332b1b-0b6c-2450-7f68-cb11160ece5a.png)

## ActionTextを導入する
~~~
$ rails action_text:install
$ bundle install
$ rails db:migrate
~~~

~~~ruby:models/post.rb
class Post < ApplicationRecord
	validates :title, presence: true

	has_rich_text :content
end
~~~

~~~ruby:views/posts/_form.html.erb
<%= form_with(model: post, class: "contents") do |form| %>

 # 略

  <div class="my-5">
    <%= form.label :title %>
    <%= form.text_area :title, rows: 4, class: "block shadow rounded-md border border-gray-200 outline-none px-3 py-2 mt-2 w-full" %>
  </div>

↓ ここから
  <div class="my-5">
    <%= form.label :content %>
    <%= form.rich_text_area :content, class: "block shadow rounded-md border border-gray-200 outline-none px-3 py-2 mt-2 w-full" %>
  </div>
↑ ここまで追加

  <div class="inline">
    <%= form.submit class: "rounded-lg py-3 px-5 bg-blue-600 text-white inline-block font-medium cursor-pointer" %>
  </div>
<% end %>
~~~

~~~ruby:views/posts/_post.html.erb
<div id="<%= dom_id post %>">
  <p class="my-5">
    <strong class="block font-medium mb-1">Title:</strong>
    <%= post.title %>
  </p>
↓ ここから
  <p class="my-5">
    <%= post.content %>
  </p>
↑ ここまで追加

 # 略
</div>
~~~

これでActionTextを導入できました。
ブラウザで確認してみましょう。
http://localhost:3000/posts/new
↓の画像のようにリッチテキストが反映されているかと思います。
![スクリーンショット 2022-06-17 8.26.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916052/7398b4b9-bc83-b4d0-b26b-c0577b67f958.png)
文章の入力やコードの入力だけでなく、画像のダイレクトアップロードにも対応しています。

⚠︎使いにくいと感じる方もいるかと思います。
そういった場合は、マークダウン形式で投稿できるGemなどもありますので、導入を検討してください。
この記事ではサンプルとして簡単に導入できていい感じになるActionTextを使用しました。
ActionTextの詳しい使い方は、以下を参考としてください。

https://railsguides.jp/action_text_overview.html

投稿機能を見やすくするために、少しだけデザインを当てます。
下記のように変更してください。
~~~ruby:views/posts/_post.html.erb
<div id="<%= dom_id post %>">
  <div class="card bg-primary text-neutral-content">
    <div class="card-body items-center text-center">
      <h2 class="card-title">
        <%= post.title %>
      </h2>
      <p class="my-5">
        <%= post.content %>
      </p>

    <% if action_name != "show" %>
      <%= link_to "Show this post", post, class: "rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
      <%= link_to 'Edit this post', edit_post_path(post), class: "rounded-lg py-3 ml-2 px-5 bg-gray-100 inline-block font-medium" %>
      <hr class="mt-6">
    <% end %>
    </div>
  </div>
 <hr class="mt-6">
</div>
~~~
何件か適当に投稿してみてください！
（キャプチャの文章は、Railsガイドより引用しています。）
以下のように表示されるかと思います。
（daisyui のテーマ次第で色が変わります。今回は「pastel」を使用しています。）
![スクリーンショット 2022-06-17 8.32.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916052/8017fb38-0577-09b2-49fc-f14261d5c32d.png)

デザインは自身のアイデアに合わせて適宜変更してください！

https://daisyui.com/components/card/

## 細かい部分の修正
トップページを投稿機能にします。
~~~ruby:config/routes
Rails.application.routes.draw do
  resources :posts
  
  root "posts#index"
end
~~~

次に、Postにバリデーションを設定します。
~~~ruby:app/modes/post.rb
class Post < ApplicationRecord
	validates :title, length: { maximum: 50 }, presence: true

	has_rich_text :content
end
~~~
Postモデルのtitleというレコードにバリデーションを設定しました。
最大文字数を５０文字に制限しています。
~~~ruby:app/modes/post.rb
	validates :title, length: { maximum: 50 }, presence: true
~~~


## Hotwire を体感してみる

Hotwireを実際に使ってみて、どんなものか見てみましょう！

と言っても、数行追加するだけで簡単に実装できます。

~~~ruby:views/posts/_post.html.erb
# 追加↓
<%= turbo_frame_tag "posts-list" do %> 　
  <div id="<%= dom_id post %>">
    <div class="card bg-primary text-neutral-content">
      <div class="card-body items-center text-center">
        <h2 class="card-title">
          <%= post.title %>
        </h2>
        <% if action_name != "index" %> # 編集
          <p>
            <%= post.content %>
          </p>
        <% end %>　

      <% if action_name != "show" %>
        <%= link_to "Show this post", post, class: "rounded-lg py-3 px-5 bg-gray-100 inline-block font-medium" %>
        <%= link_to 'Edit this post', edit_post_path(post), class: "rounded-lg py-3 ml-2 px-5 bg-gray-100 inline-block font-medium" %>
        <hr class="mt-6">
      <% end %>
      </div>
    </div>
    <hr class="mt-6">
  </div>
<% end %>　
~~~

これでトップページにアクセすると、↓のようになります。
![スクリーンショット 2022-06-18 9.56.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916052/5bd6b7c2-8fd7-c5a8-3131-a0c672a7e816.png)

「Show This Post」を押下すると、Postの内容がSPA風に表示されます！
![スクリーンショット 2022-06-18 9.57.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/916052/cc3a795c-551a-3a74-7cae-901fa3ab6130.png)

URLが変わっていないのも確認できるかと思います。
今回は体感していただく目的ですので、デザインや機能性の部分は目を瞑ってください。
次回以降拡張していきます。

## 次回は
次回は投稿機能にgemを追加して拡張していきます。
また、今回体感したHotwireをさらに使用していきます！