$shibayu36->blog;

クラスター株式会社のソフトウェアエンジニアです。エンジニアリングや読書などについて書いています。

Rails勉強し直している - Webアプリケーション編

Rails勉強し直している - DB操作編 - $shibayu36->blog;に引き続きRailsを勉強し直している。今回はHatena-TextbookのWebアプリケーションの課題を通して学習した。

作ったもの

diffはこの辺。ユーザーが存在する前提で、記事のCRUD処理を実装した。

今回学んだことを雑多に記録していく。

/:username/entries/:id のようなルーティングを作る方法

あるユーザーの記事一覧というURLを作るため、/:username/entries/:id というルーティングが作りたかった。gitlabのこの辺とかを参考にすると、scopeを使うと良さそうであった。

例えばこんな感じ。

  scope '/users/:username' do
    resources :entries
  end

またルーティングヘルパーにUserモデルを渡すだけで /users/shibayu36/... みたいなURLを作って欲しい。今回はそこまではやらなかったが、モデルにto_paramというメソッドを作ることで、このようなことができそうだ。参考: https://github.com/gitlabhq/gitlabhq/blob/5c2b90563fd488c3e54c3ff1183e4a2bb9c1caba/app/models/project.rb#L1489-L1495

RecordNotFoundの例外が出たときに自動で404を表示する

ApplicationControllerでrescue_fromを書いてハンドリングしてあげることで対応できる。大域脱出を使うのは微妙と思いつつ、GitLabやrubygems.orgでも普通に使われているし、そういうインターフェースであると考えれば良いと感じた。

class ApplicationController < ActionController::Base
  rescue_from ActiveRecord::RecordNotFound, with: :record_not_found

  private

  def record_not_found
    render plain: '404 Not Found', status: :not_found
  end
end

Tailwind CSSwatchを別のDockerコンテナで実行

Tailwind CSSを導入し、bin/rails tailwindcss:install を実行すると、Procfileで管理されて bin/dev で複数プロセスを実行するモデルになった(参考)。

このやり方はコンテナ利用の場合だと微妙だなと思ったので、docker-compose.ymlで別のコンテナを立ち上げてwatchするようにしてみた。この時、tty: trueを設定してあげないと起動直後に落ちてしまうことに注意。

https://github.com/shibayu36/rails-playground/commit/a669cbf7cef8964822c6f8324e625a0c4315dd1f

  tailwind:
    build: .
    command: bin/rails tailwindcss:watch
    tty: true
    volumes:
      - .:/app

その上で結局Tailwindを使ってデザインするのがだるくなって、ひとまず今回は撤退した。

参考: tailwindcss exits even with —watch - only on Docker · Issue #44048 · rails/rails · GitHub

he solution was to add tty: true to docker-compose.yml since esbuild terminates when stdin is closed. Maybe tailwindcss behaves similarly.

Dockerコンテナ内で立ち上がったRailsアプリケーションをdebug.gemでデバッグ

https://github.com/ruby/debug#remote-debugging のようにRemote debuggingの設定をしておくと良いらしい。https://inspirnathan.com/posts/147-debug-ruby-on-rails-in-docker/ の記事も参考になる。

自分はdocker-compose.ymlのデフォルト設定でRails起動時に必ずrdbgを通すようにするのは微妙だなと思い、debug.gemを使いたいときに使うoverride用のdocker-composeファイルを用意することにした。

docker-compose.with-debug.yml (https://github.com/shibayu36/rails-playground/commit/5e8ba91d6dd445843c784ea6144368932cbf4b84)

version: '3'
services:
  web:
    command: rdbg -n --open --host 0.0.0.0 --port 12345 -c -- bin/rails s -p 3000 -b '0.0.0.0'
    ports:
      - 12345:12345

このファイルを用意した状態で次のようにdebug.gemを通した状態でRailsのコンテナを起動する。

docker compose -f docker-compose.yml -f docker-compose.with-debug.yml up

起動したら以下のコマンドでアタッチすると良い。

rdbg --attach 12345

参考

まとめ

今回はWebアプリケーションの課題をRailsで解いてみて、Railsの学び直しをしてみた。本当に簡易的ではあるが開発の雰囲気を掴めてよかった。

Docker・MySQL・RuboCop・RSpec・factory_botを導入したRailsプロジェクトを作る

Rails勉強し直している - DB操作編 - $shibayu36->blog; の初期セットアップ部分で言及したとおり、Rails・Docker・MySQL・RuboCop・RSpec・factory_botという構成でやってみた。その構成を初期セットアップする方法についてブログ記事に残しておく。

作ったプロジェクトは https://github.com/shibayu36/rails-project に公開している。

Railsプロジェクトの作成

rails newを使って作成する。databaseをMySQLに指定する。テストは後でセットアップするため--skip-testする。それ以外もひとまず不要そうなものは除外する。

rails new rails_project --skip-test --database=mysql --skip-action-mailer --skip-action-mailbox --skip-action-text --skip-active-storage --skip-action-cable

RSpecの導入

以下をGemfileに入れ

group :development, :test do
  gem "rspec-rails"
end

bundle installとrspec:installを実行。

bundle install
bin/rails generate rspec:install

Dockerの導入

導入がちょっと複雑なので、e2d7b7bd のcommitを見ると早い。ポイントとしては

  • 環境変数でDBアクセスの設定をできるようにする
  • named volumesを使えば簡単にMySQLのデータを永続化できる
  • pidファイルのハンドリングをしないと2回目以降立ち上がらなくなってしまう
  • MySQLの接続ホストをlocalhostにすると、port指定してもmysql.sockを見てしまうので、127.0.0.1を明示的に指定する

RuboCopの導入

Gemfileに

group :development do
  gem 'rubocop', require: false
  gem 'rubocop-rails', require: false
  gem 'rubocop-rspec', require: false
bundle install

後は.rubocop.ymlに以下のような設定をし、自分でカスタマイズしていく。

require:
  - rubocop-rails
  - rubocop-rspec

AllCops:
  Exclude:
    - "vendor/**/*"
    - "db/**/*"
    - "config/**/*"
    - "bin/*"
    - "node_modules/**/*"
    - "Gemfile"
  NewCops: disable

factory_botの導入

先にmodelを作っておく。

bin/rails generate model User name:string:uniq

Gemfileに追加し、bundle install。

group :development, :test do
  gem "factory_bot_rails"

後はfactory_botのための定義をしていくとよい。851ad8 のcommitを参考。ポイントとしては

  • spec/support/以下を自動で読み込む設定を入れた
  • spec/support/factory_bot.rb でFactoryBot::Syntax::Methodsをincludeすることで、namespace指定なしでcreate(:user)とかできるようにした
  • factory定義ではsequenceを使うことで、同一の名前をつけないように

まとめ

以上でDocker・MySQL・RuboCop・RSpec・factory_botを導入したRailsプロジェクトを作ることができた。今後Railsプロジェクトを作るときの参考にしたい。

子供の熱性けいれんを初体験した

すごく焦ったけど良い形で対応できたので書いておく。

状況

子供が40度近い熱が出たので小児科へ。インフルエンザA型の診断を受けて薬をもらう。自転車での帰り道に違和感を感じたので後ろを振り向いたら、子供がけいれんを起こしていて泡も吹いていた。

熱性けいれんのことも頭によぎりつつ、今まで体験したことなかったので自転車を停めてすぐに119連絡。呼吸を確認してくださいと言われたので確認すると大丈夫だった。けいれんが治っても意識は戻らなかったので救急車の到着を待つ。救急車の中でけいれんの様子を救急隊員に報告する。この時熱は40.6度まで上がっていた。受け入れ病院の電話を聞きながら1~2個から断られているのを聞いて、医療崩壊怖いと感じる。

病院に着いた時、反応は薄いが多少子供の意識が回復していた。けいれんの様子や意識の回復の様子から考えて、単純性の熱性けいれんだろうと病院が判断。けいれんを防ぐ坐薬を入れてもらい、しばらくしてから帰宅した。

経験と知見

素人の知見は怖いので熱性けいれんの詳細は病院のサイトを見てもらいたい。ただ自分の経験をまとめておくと参考になりえると思うので、書いておく。

  • 自転車で違和感を感じたら、すぐに見てあげることが大事
    • 自転車で違和感を感じた時、最初は子供が自転車で寝たときのいつもの重みを感じて、寝ちゃったのかなと感じた。しかし、細かく振動しているなど、いつもと何か違うぞという違和感を感じた。そういう時、直感を信じてすぐに見てあげることが大事
    • このときの直感を養うためには、いつも育児に関わる必要があるので、育児をしましょう
  • インフルエンザのけいれんはとくに怖いので、けいれんの様子を観察して覚えておくことが大事
    • インフルエンザでのけいれんは、重篤な症状の可能性もある。重篤かそうでないかの判断軸としてけいれん時の様子が大事なので、けいれん継続時間やけいれんの左右対称性を観察しておくことが大事なようだ
    • 熱性けいれんの初期対応はちゃんと医療機関のサイトを参考にしましょう。たとえば https://caps-clinic.jp/febrile-seizure/ とか
  • 対応は安全側に倒す
    • 熱性けいれんの知識は多少あったので、「救急車を呼ぶのは様子を見てから」みたいな文章が頭によぎった
    • しかし、これまで起きてなかったのにはじめて起きたこと、外で起きたことなどから、とにかく安全側に命が助かる方向の判断をした方が良いと考え、即座に119番連絡をした
    • その後に調べてみると、そもそも意識がしばらく戻らなかったし、インフルエンザきっかけという理由もあったので救急車呼ぶ案件っぽかった。安全側に倒して良かった
  • マインドフルネス瞑想をやっていたのが、緊急対応に意外と役に立った
    • けいれんを最初に見た時、正直めちゃくちゃ慌てていた。その状態で冷静に判断と対応をしなければならない
    • 自分は1~2日に1度くらい体調を整えるためにマインドフルネス瞑想をしているのだが、そのおかげか「慌てている自分」に早めに気づけて、「どういう精神状態でも呼吸をゆっくりすると穏やかになる」という知識もあった
    • 119番連絡している時もとにかく呼吸をゆっくりすることを意識したら、ある程度落ち着いて連絡できた

まとめ

熱性けいれんをはじめて対応すると本当に慌てますが、冷静にやっていきましょう...インフルエンザも流行していて怖いですね。

昨日はブログの予約投稿をしていたので、タイミング的に救急車に乗りながらブログを更新する人みたいになってて笑ってしまった。