はじめに
おはようございます torihaziです
現在、朝の7時24分です。
リリースまであと1週間ちょいしかないので実務と並行してやるしかありません
今日はテーブル構造とDocker立ち上げ、認証までをやりたいと思います
途中で技術選定も入れていきます。
技術選定
ここに追加していく感じです
- frontend
- Nextjs
- backend
- Rails 7
ディレクトリ構成
このプロジェクトのディレクトリ構成についてです
top/ ├─ table/ │ ├─ Dockerfile │ ├─ table.pdf ├─ back/ │ ├─ rails_project/ ├─ front/ │ ├─ nextjs_project/
このtable、back、frontをgit管理していこうと思います。
テーブル構造
ER図を書くためにこちらを使います。
理由は手間が少ないから。よくあるツールだとパワーポイントみたいな感じで
四角形選択して、大きさ調整して、クリックして文字入力して、、、
という感じで面倒なので。
んじゃ書き始める
詰まったとこ
こんな感じで詰まったとこをメモ程度に書き残します。
これ使わないとだらだら続いてみづらいためです。
1つ目
カラムの属性でstringは1~255文字、textは1~むっちゃ長い文字。
2つ目
タグはどういうふうにテーブル管理するか。
diary(日記)は0個以上のタグを持ちうるし、タグもまたそう。
ということで中間テーブル使うのが良さそう。
https://zenn.dev/kibe/articles/0f3cc25bac273a
3つ目
外部キー制約について
よくある親が削除されたらその子のレコードも削除したいときに設定する
dependent: :destroy。
これについては DBに対して直接設定する ON DELETE CASCADEという方法もあるらしい。
前者はコールバックを設定できるらしいが、後者は無理らしい。
てことで慣れてる前者で。方法があるだけ知っておこう。
dependent: :destroy: Railsアプリケーションを通じての操作時のみ動作します。 モデルのコールバックが実行されます。 関連するレコードの削除をより細かく制御できます。 ON DELETE CASCADE: データベース直接操作時にも動作します。 パフォーマンスが若干良いです。 コールバックは実行されません。
一応できた。けどあれだ。あっているのかわからない。
まぁいいか。Claudeに助言求めたけど概ねいいらしいし、下記の要件は満足してると思う。
ということでできました。
開発環境構築
Dockerで作ります。
これを参考にしながら。
Rails 7 x React 18(Javascript) x Docker 環境構築 #JavaScript - Qiita
. ├── back │ ├── Dockerfile │ ├── Gemfile │ ├── Gemfile.lock │ ├── entorypoint.sh │ └── 作業ディレクトリ ├── front │ └── 作業ディレクトリ └── docker-compose.yml └── .env
docker-compose.yml
version: "3" services: db: image: postgres:latest volumes: - postgres_data:/var/lib/postgresql/data environment: - POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} - POSTGRES_DB: app_development ports: - "5432:5432" back: build: context: ./back dockerfile: Dockerfile volumes: - type: bind source: ./back target: /app command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" ports: - "3001:3000" environment: DATABASE_PASSWORD: ${DATABASE_PASSWORD} TZ: Asia/Tokyo RAILS_ENV: development depends_on: - db volumes: postgres_data:
詰まりました。
これでdocker compose buildしたらいけるかな。
いかない。なんで。
services.db.environment.[0]: unexpected type map[string]interface {}
dbのとこのenvironmentがおかしいみたい。
書き方に2通りあるんですね。初めて知りました。
キーバリューかリスト形式か。 = なら リストで、:なら-がいらないらしい。
ymlの記法、勉強しないとダメですね。この前も言った気がしますが。
ということでリスト形式他で使ってなかったのでキーバリューにしました。
再度トライ。行けたみたいですね。新しい発見でした。
backend
まずはコマンド1発
docker compose run --rm back rails new . --api --force --no-deps --database=postgresql --skip-docker
Gemfile変わったので再ビルド
試しにdocker compose up してみます。
http://localhost:3001 を見ると。。。
白紙。
dockerのログには
ActiveRecord::ConnectionNotEstablished (could not connect to server: No such file or directory back-1 | Is the server running locally and accepting back-1 | connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"? back-1 | ):
何やらpostgreと繋げないらしい。調べるとdatabase.ymlのhostが問題らしい。
ということで見て編集
default: &default adapter: postgresql encoding: unicode # For details on connection pooling, see Rails configuration guide # https://guides.rubyonrails.org/configuring.html#database-pooling pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> ここから追記 host: db
docker compose restartして見ると
とりあえず繋がりはしたそうです。
パスワードの設定です。password: <%= ENV['DATABASE_PASSWORD'] %>
これをhostの下に追記
再度 docker compose restart。
接続するuserの設定です。 username: postgres
をpasswordの下に追記
再度 docker compose restart
ようやく現れました。
ちょっと待って。経験則でこれら設定しなきゃいけないのは理解した。でもなんで。
まーあとで追求しよう。
あとはcorsだ。
詳しいやり方はさっきのqiitaを参照。
ということでbackendの環境構築終了。
frontend
これはnextjsをapprouterで入れるだけ。
ただUIコンポーネントライブラリは何にしよう。
実務ではshadcnを使っていますが、そうですね。
調べてランキングtopだったものでいいでしょう。
ということでmaterial uiに決定です。
ReactのおすすめUIコンポーネントライブラリ|Kinsta®
docker-compose.ymlがある階層で docker compose run --rm front bash
して
・・・
とやろうかと思っていたんだけど。
frontendはdocker使わないことが一般的らしい。確かに実務でもそうだし。
ということでこれはローカルでやろう。
docker compose ymlがある階層に移動して npx create-next-app@latest front
とする。
(ここはなんかダサい。反省ポイント)
てことで
✔ Would you like to use TypeScript? … Yes ✔ Would you like to use ESLint? …Yes ✔ Would you like to use Tailwind CSS? …No ✔ Would you like to use `src/` directory? … No ✔ Would you like to use App Router? (recommended) … Yes ✔ Would you like to customize the default import alias (@/*)? …Yes ✔ What import alias would you like configured? … @/*
ということで立ち上がったのでgit管理して先に進む。
終了。
https://github.com/torihazi/diary_front
https://github.com/torihazi/diary_back
これを元に開発を進めていく。
認証画面作成
approuterで開発を進めていくわけだが、今気づいた。
pages-routerと何が違うのか知らない。調べる。
かなり重い。切り替え。pages routerでやることにした。
この間 1.5時間。
これも反省ポイント。pages-routerもまだあまり知らないのにその上位互換?の
app-routerに手を出すべきでない。
画面はこんな感じ。
react-hook-formとzodを入れる必要がありそう。あとMUIだ。
まずMUI入れないと。
入れるのにも一苦労。
まずMUIをいれるのに
npm install @mui/material @emotion/react @emotion/styled
そこからnextjsに統合するのに
npm install @mui/material-nextjs @emotion/cache @emotion/server
これなのね。MUI nextjsってやって調べて出てきたのは後者だったから
それやったら全部いけるのかと思ってた。
Next.js integration - Material UI
ということで修正したのがこれ。
_document.tsx
import { DocumentHeadTags, DocumentHeadTagsProps, documentGetInitialProps, } from "@mui/material-nextjs/v14-pagesRouter"; import { Html, Head, Main, NextScript, DocumentProps, DocumentContext, } from "next/document"; export default function Document(props: DocumentProps & DocumentHeadTagsProps) { return ( <Html lang="en"> <Head> <DocumentHeadTags {...props} /> </Head> <body> <Main /> <NextScript /> </body> </Html> ); } Document.getInitialProps = async (ctx: DocumentContext) => { const finalProps = await documentGetInitialProps(ctx); return finalProps; };
_app.tsx
import "@/styles/globals.css"; import { AppCacheProvider } from "@mui/material-nextjs/v14-pagesRouter"; import type { AppProps } from "next/app"; export default function App({ Component, pageProps }: AppProps) { return ( <AppCacheProvider> <Component {...pageProps} /> </AppCacheProvider> ); }
ヘッダーってどう作ろう。
なんかsxで色々指定しないとcssいじれないのか。めんどくさいな。
sxは普通のcssか。かったるいな。
そう考えるとtailwindって楽だったのかな。
まぁいいや。慣れよう。
LPで苦戦してる。
コンポーネントいい名前見つからないから Claudeに考えてもらった。
<div> <HeroSection /> <FeaturesList /> <DiaryPreview /> <SignUpForm /> </div>
こんな感じ。
ダークモードにできるようにするのはあとでいいや。
最低限の見た目をぽくする。
これができたらログイン画面にいこう。
んー。めっちゃストレス。
確かにshadcnめっちゃ楽な気がする。tailwindでちゃちゃっとできるし。何より補完が効くから早い。
MUI、毎回sxって書いてやらなきゃいけないのだるいな。自分のやり方がおかしいのだろうか。
時間がかかる。
"機能だけは欲しいけど、見た目はこっちでいじらせて"ていうニーズがわかった気がしなくもない。
次は絶対shadcnでやろう。cssの設定がだるすぎる。慣れてないからか?
レスポンシブのやつが長い。fontSize: {md: OO, xl: OO}なんとかってやらないとダメ。
tailwindなら OO xl:OOって設定するだけでいいのに。
とりあえず慣れてきた。frontはモックでやってる。
現状。
NextjsのリンクとMUIのリンクを使うときに詰まったが、これで解決
めっちゃ進捗悪い。
今までできていたと思っていたのは他人が作った抽象化されたコンポーネントを使い回して
書いていたからだ。多分今の実力は元々こんなもん。知らんけど。
テキスト入力するとき毎回Typography書かないといけないのめんどい。
componentにspanとかpとか設定して分けられるにしても。
自分はdivとかpとかspanのclassNameにtailwind書いて行った方が早いと思うんだけど。
デザインで詰まったとこ。css
<Typography component="p" sx={{ overflow: "hidden", display: "-webkit-box", WebkitLineClamp: 2, WebkitBoxOrient: "vertical", textOverflow: "ellipsis", }} > {diary.content} </Typography>
tailwindだともっと短くかけた気がするんだが。
linecrampは使ったことあった。がwebkitとか添えないとダメらしい。
登録フォームまでやりたかったが、現状。今日はここまで。
終わりに
反省。進捗が悪かった。
敗因は色々。MUIのキャッチアップに時間がかかった。
集中が続かなかった。どう作ろうかで悩みすぎた。
app-routerいけると思ったけど、よくわからなかったのでpages-routerに切り替えるまで時間がかかった。
初手からダークモードの実装に入ろうとしてた。
自分が欲しているコンポーネントがMUIのどれに当たるかで探してたら時間がかかった。
ただcssの知識は上達はしていると思う。こうすればこうなる、ほらね、という流れが多くなってきているし
やれることが増えてきているのはいいことだと思う。
少し完璧主義になっているのだろうか。どうしても気になって先に進めない、というところが多かった。
というか認証のfrontもbackもやってないことに今気づいた。
明日やらないと。
ということで今日はここまで。