【第18週】パRails輪読会🚂 (2023-12-18~ 2023-12-22)

tags: パRails🚂

目次


2023-12-18(月)

ファシリ

@motohiro-mm

ドライバー

@moegi

読んだところ

6-5-2 319p columnから
6-6-1 「イベント編集機能を作る」まで。
PR:https://github.com/PerfectRubyonRails-Rindoku/Perfect_Ruby_on_Rails_Ch6/pull/11

次回

6-6-2 「イベント削除機能を作る」から。🚂

学んだこと・感想

  • @sharoa

    • コラムの名前が重要のところで、railsでは規約によってデフォルトの名前が自動的に決まるものもあるが、それが実態を表していないと感じた場合は積極的に変更していくことが大事、とのことだそうです。自分にその判断ができるのか正直微妙なところですが、判断ができるようになっていきたいな〜と思いました。
    • イベント詳細ページに編集ボタンを追加するにあたって、Event#created_by? メソッドを使用して、イベントを作成したユーザーがイベントを詳細ページを閲覧した時のみリンクを表示できるようになる。
    • Bootstrap では、コンテナを12個のグリッドに分割してレイアウトを制御しているそうで、hamlファイルの中の.col-8.col-4を数値を変えることで表示が変更したのが確認できてよかった。
  • @hiromisugie

    • Railsがデフォルトで決めた名前であっても、実態に合わせて変えていくことが必要になることもある。(名前重要という非常に重要そうなコラムを皆さんと確認できて良かった)
    • 以下のメソッドの中身は、1行目ではログインしてなかったら早期returnで即false、ログインしてたら2行目に移り、オーナーID(イベント作成者)とユーザーID(今閲覧している人)が一致しなかったらやはりfalse。一致したらtrueが返る(=viewの方で「イベント編集」ボタンを表示できる)、ということ。
      早期returnも苦手、unlessも苦手で、早く慣れたい…!けど、パズルのようで楽しい。
def created_by?(user)
  return false unless user
  owner_id == user.id
end
  • @moegi29

    • コラムの名前重要のところを読んでlsコマンドのプラクティスのときに変数名のつけかたでも苦戦したのを思い出しました。
    • current_userの関連を使わずowner_idで絞り込む場合、絞り込みがなくてもエラーにはならない。でも、忘れてしまうと誰でもイベント編集や更新が可能になってしまうというところは注意。
    • SJRで実装。SJR:サーバサイドでJavaScriptのコードを生成しそれをレスポンスとして返すJavaScriptの実行方法
  • @shodan

  • @ayu-0505

    • 「bootstrapが12分割を基本として考えられる」ことは知らなかったので勉強になりました!(他の参考書とかでも謎の数字と思っていた気がします)
    • コラムの名前重要について、確かに課題をしていく中で名前で分ける必要を感じて後から修正することが多いので(idmentioning_idみたいに)、なるほどと思いました。
  • @motohiro-mm

    • created_eventsが今後他の関連づけるときに名前が衝突するためにあえてその名前にした事がわかって納得しました。名前大事
      • 自分のOOPプラクティスの提出物の名前付けが不安になってきました
    • bootstrapが.col-で12分割していることを初めて知りました!勉強になりました〜
    • 「また、関連付けを使わずowner_idで絞り込む場合、絞り込みがなくてもエラーにはならないので時折忘れてしまいます」の部分が理解が曖昧…
    • 自分で出ていたエラーはsafariでもダメだったので、なんでエラー出てるのかこのあと調べます〜
      • localhost127.0.0.1の違いでした

2023-12-19(火)

ファシリ

@sharoa

ドライバー

@sadanora

読んだところ

6-6-2 「イベント削除機能を作る」から
6-7-1 「イベント参加機能の作成」の途中まで。
PR: https://github.com/PerfectRubyonRails-Rindoku/Perfect_Ruby_on_Rails_Ch6/pull/12

次回

6-7-1 329p 「イベント参加処理の作成」から。🚂

学んだこと・感想

  • @sharoa

    • イベント削除機能を作るにあたって、論理削除ではなく単純な物理削除を実装した。論理削除とは。。。削除フラグを追加して実際にはレコードを削除しない手法のこと。
    • destroyメソッドではなくdestroy!メソッドを利用することで、想定外の事態が起きた時にすぐ気づけるようにしている。
    • イベント参加機能の作成で、「コメントを正しく入力すると参加が完了する」とあったが、空文字やnilを許可としているのに少し、え?と思ったけど、ただの空欄でも参加はできるよってことでそういうのは普通にあるか、と気づきました!
  • @hiromisugie

    • 論理削除は、削除フラグを追加して削除したように見せているが実はレコードが残っている状態。物理削除は、レコードから削除する。
      • ブログサービスとかで、投稿した記事をゴミ箱に入れると記事一覧からは消えるけどゴミ箱には残っている(一定期間でそこからも消える)みたいな機能があるけど、それも似たような仕組みなのかな…?
    • user_idカラムでnullを許可すると、イベントを作成したユーザーが退会してuser_idが無くなってもエラーにならずイベントだけは残る、みたいなことかなぁと思った。
      • これまたブログとかSNSで、作成者がいなくなっても投稿だけ残ってるみたいな状況を見たことがある)
    • ユーザーが同じイベントに重複して参加できないようにするためにユニークインデックスを追加する。1つ1つの機能でエラーやおかしな状況が生まれないような細かい設定が必要なんだなと思った…!
    • ハッシュリテラルの種類、うろ覚えになっているのでチェリー本で復習しないと、、、
  • @sadanora

    • %button.{ "data-toggle": "modal", "data-target": "#createTicket" }じゃなくて%button.{ "data-toggle" => "modal", "data-target" => "#createTicket" }
      • :を使ってしまうとうまく動かないみたいなので、=>を使う
        • 試したらどっちでも動いたのでそんなこともないみたい。書き方の好みの問題ってことでいいのかな?
  • @motohiro-mm


2023-12-20(水)

ファシリ

@sharoa

ドライバー

@ayu-0505

読んだところ

6-7-1 329p 「イベント参加処理の作成」
PR: https://github.com/PerfectRubyonRails-Rindoku/Perfect_Ruby_on_Rails_Ch6/pull/13

次回

6-7-1 331p 「参加者一覧表示機能を作る」から。🚂

学んだこと・感想

  • @sharoa

    • :=>について、昨日の話から、sadanoraさんが確認してくれて、:でも動くということがわかった。(本で2パターンで書かれているのが気になる。)
    • イベント参加処理を作って、その流れが見れたのがすごく良かった。
    • 参加者が重複しないように設定していたところも確認できたのも良かった。sugieさんナイスな質問でした。
    • 参加コメントでエラーがでた際に、その画面をリロード(遷移など)をしない限り、そのまま残っていた。消したい場合はそうなるようなコードを追加しないとダメそう。
  • @moegi29

    • パーフェクトRuby on Rails【増補改訂版】サポートページの正誤表だとどちらも => だったのでより謎が深まった。
    • 参加コメント入力エラーのエラーメッセージのモーダルを閉じた後もそのまま残っている状況、ユーザーが重複して登録できないという挙動をHTMLとRailsからの視点でそれぞれみれて動きのイメージがつきました
    • 昨日帰宅が遅くそこから巨人を観てしまい寝不足なので終始ぼーっとしていました 睡眠大事だと思いました
  • @sadanora

    • Ticketモデル
      • 同じユーザーの参加表明ができないようにEventとUserにユニークインデックスを貼っている。
      • この状態で同じユーザーの参加表明をしようとするとActiveRecord::RecordNotUniqueが発生する
      • httpステータス的は500になっていた
      • sugieさんの質問のおかげで細かい動きが確認できてよかったです。
  • @ayu-0505

    • ハッシュの記法である=>:について、RailsとRubyでまた作法や挙動が違うかもしれないという可能性を知ることができた。
    • モデルにユニーク制約をつけたことにより、画面上は特に変化がないように見えて、コンソール上ではロールバックしてエラーが出ていたので、ログを見ながら開発する必要性を感じた。
    • 昨日休んだら、モーダルが出来上がっていてびっくりしました。モーダルの作り方は全然分からないので、また参考にして調べたいと思います。
    • 久しぶりのドライバーで少し緊張しましたが、滞りなくCH6をクローンできてよかったです。
  • @hiromisugie

    • ハッシュロケット(=>)というと、Rubyのハッシュと結びつけて考えてしまうけど、Railsのお作法で=>を使う場合にちょっとルールが違う場合があるかもしれない??なんというか難しいなと思いました。
    • 前回のマイグレーションファイルでticketsにユニークインデックスをつけていたので同じユーザーが2度参加できない、というのを試せて良かった。ただ、コントローラやビューを何も設定してないので、今のままだと実用には耐えないこともわかった。
    • モーダルを閉じてもエラーメッセージが残る問題。BootstrapでモーダルにしてJSでエラーを出しているが故に起こっていると思うので、変に洒落てモーダルとかJSとか使わなくてもいいなと個人的には思いました笑。(そうすると完了画面とか用意しないといけないから、どっちが手間なのかはちょっとわかりませんが)
    • 未ログイン状態でどうなるのかを次回確認したい
  • @motohiro-mm

    • 前回追加したadd_index :tickets, %i[event_id user_id],unique: trueがきちんと動作して、重複して参加登録されずにActiveRecord::RecordNotUnique(間違ってたらすいません)が出ているところを見れて良かったです!

2023-12-21(木)

ファシリ

@sadanora

ドライバー

@shodan

読んだところ

6-7-1 331p 「参加者一覧表示機能を作る」から
335pまで。
PR:

次回

6-7-1 336p 冒頭から。🚂

学んだこと・感想

  • @sharoa

    • 昨日確認するのを忘れていた「未ログイン状態で『参加する』ボタンを押した時に実行されるアクション」を今日確認できて良かった。きちんとauthenticateメソッドが呼ばれていました。
    • includespreloadeager_loadのどちらかを選択して実行している。
    • 実際の現場ではincludesは使わない。(どちらが実行されているかが不明でそれは良くないこと。)
    • explainも含めて、preload、eager_load、includesを調べてみたいと思います。
  • @motohiro-mm

    • 未ログイン状態での参加する→ホームに戻るが確認できて良かったです!
    • N+1問題対策のincludespreloadeager_loadをどちらかを選んで実行している
      • 実際の仕事ではどちらのパターンのSQLが実行されているかわからないのは良くないので、includesは使わない
      • explainを使うとDBのパフォーマンスとか速度とかそういうのを見ることができるので、それらを見てpreloadeager_loadのどちらが良いかを自分で判断する
    • ビューにロジックを書くと見辛くなるのでヘルパーにメソッドを追加する方が良い
      • 数が多くなるとヘルパーメソッドが見辛くなる&ヘルパーメソッドはオブジェクト指向的ではない
      • プレゼンター用gem(DraperやActiveDecoratorなど)を利用すると、モデルに紐づいた形でロジックを書けるので、分かりやすくなる
  • @ayu−0505

    • N+1問題のincludesメソッドはpreloadeager_loadの両メソッドのうちのどちらかをRailsが自動選択して行なっている。どのような挙動になるか分からないので、仕事においては基本使わない。
    • explainメソッドを使用するとDBにおけるパフォーマンスを計測できるので、発行されるSQLとその結果を付き合わせながら、どちらのメソッドを使うか自身で選択した方が良い。
    • 「ヘルパーメソッドは書き方がオブジェクト指向的ではない」が最初意味がよく分からなかったのですが、shodanさんが質問してくれたおかげで、なんとなく「どこにも所属していないように見えるから」ということがふわっと理解できました。
  • @moegi29

    • N+1問題対策のincludesメソッドはpreloadeager_loadのどちらかを選択して実行してくれている
    • explainメソッドで発行されているSQLを計測できる。動くことが第一だけどパフォーマンスも気にかけられると良い。データが溜まっていくようなサービスを作る場合はパフォーマンスも考えたほうが良さそう。
  • @sadanora

    • ActiveRecordのincludespreloadeager_loadどちらかを選んでよしなに実行してくれる
      • どっちが高速かわかっているならincludesを使わずに明示的にそれぞれのメソッドを実行した方がよい
      • explainでSQLの実行結果を確認できる。
    • Decorator
      • デザインパターンの一種
      • ヘルパーメソッドが増えすぎると見通しが悪くなるので、ActiveDecoratorのようなgemを導入してDecorator層を設けるといいかも。
  • @hiromisugie

    • includesメソッドは、preloadeager_loadをよしなに選んでやってくれる。お仕事では、「よしなに」だと困るのでどちらが良いかを検証した上でpreloadeager_loadどちらかを選んで使う。SQLの読み込みを見比べるなどしてどちらが良いか確認する。(explainというのが使える??)→Railsガイド:EXPLAINを実行する
      • N+1問題、まだまだピンとこない、、、が、ここはお仕事でも非常に重要なポイントとのことなので、ちゃんと理解しないといけないところ。
    • ヘルパーメソッドは便利だけど多用しすぎるのも良く無いらしく、たくさん使いそうだったらプレゼンター用のgemを導入を検討すると良い
    • 「ヘルパーメソッドはオブジェクト指向っぽくない」とは?→ヘルパーメソッドだと何のメソッドかちょっと理解が難しくなる可能性があるけど、プレゼンターでhogeメソッドを作ってuser.hoge.〜となっていると、少なくともuserモデルの何かの状態だなとあたりをつけることができる。完璧に理解できたかちょっと不明ですが、なるほど!と思いました。

2023-12-22(金)

ファシリ

@motohiro-mm

ドライバー

@shodan

読んだところ

P336 「実際のキャンセル処理を〜」 から P340 COLUMN「コントローラの粒度と名前付け」 まで

PR:https://github.com/PerfectRubyonRails-Rindoku/Perfect_Ruby_on_Rails_Ch6/pull/15

次回

P341 「6-8-2 退会処理の作成」から🚂

学んだこと・感想

  • @sharoa

    • find_by!やticket_destroy!のように感嘆符!をつけて例外を発生させるコードにしている。
    • N+1問題を自分で察知できるか正直不安なので、このbulletをあとで入れてみようと思います。
    • いつ入会したっけ?というmotohiroさんの質問に、確かに!と気付かされました。今よくあるサービスではこういった類のものが多く、それの理由がわかって良かったです。(めっちゃ端折ってすみません😅)
    • resourcesメソッドで紐づけられる基本の7つのアクション以外でアクションが新しく欲しくなった時には新設するのではなく、別のコントローラーを作る、という考え方もある。
  • @hiromisugie

    • N+1を検知してくれるgemがある。これは便利そう…!導入必須ではと思ったが、毎回警告されてしつこいとかの事情もあるので、慣れてきたら必要に応じて使う、という感じで良さそう。自分としてはひとまずどこかで試してみたいなと思いました。
    • とあるモデルでアクションするときに、必ずしも同名のコントローラで行うわけではない。7つの基本アクション以外のアクションが必要そうになったら、それはControllerを新設するタイミングかもしれないので、立ち止まって考えてみるべし。(「コントローラと仲良しなのはモデルではなくルーティング」)
    • このアプリでは、GitHubログインした時点でUserモデルがcreateされ、すなわち「入会」している。
    • 「退会」とは、UserモデルがdestroyされてUser情報が無くなること。それはUserControllerでやりたくなるかもしれないが、RetirementControllerを別で作ってcreateすることで退会を実現する、というやり方がある。
    • ちなみに、見返していたら「入会」もUserControllerではなくSessionControllerでcreateしていた!(必ずしもモデルと同名のコントローラーでアクションするわけではない、の例)
  • @ayu-0505

    • find_by!のように意図的にエラーを発生させてユーザーに404画面を表示させる、というテクニックがまだ使いこなせないです。
    • N+1問題のアラート用gemのBulletは実際の開発現場でも利用することがあり、初心者のうちにアプリ開発するなら入れておいた方が良いかも。
    • ユーザー退会時に「退会済みユーザー」という表示をさせる場合はNOT NULL制約をつけない。(コメントプラクティスで同じようなことをしたくて、これを外すのに苦労しました)
    • 退会用のretirementsコントローラーの作成は派生的でなかなか難しかったです。
    • 大手サービスのログインを利用する方法は、セキュリティ面やユーザーの利点で広く活用され始めている。
  • @shodan

    • p338の、将来退会ユーザが出てきた時に、関連するeventsテーブルのowner_idがnullになるようにするために、初めはNOT NULL制約を付けない、というのはプラクティスでやらかしてハマったことがあります。
    • とりあえず先に、なんとなくNOT NULL制約を付けていたら、ユーザを消した時にDBのエラーになってしまった。
    • N+1問題が起きたら教えてくれるgemは自作サービスに入れようと思いました👀
    • コントローラに基本の7つ以外のアクションを生やしたくなったときは、立ち止まってコントローラやリソースの構成を考える。
    • コントローラと強く結びついているものはモデルというよりかはルーティングという意識(コントローラはルーティングを通ってきたものの交通整理役)。
  • @moegi29

    • コントローラにおけるインスタンス変数はビューに渡すオブジェクトを表すので不必要にインスタンス変数を利用しないほうが可読性が高くなる。なるほど~と思いました
    • Rails6だとremote: trueオプションを追加することでAjaxを利用できる
    • bulletというgemがN+1でエラーを出してくれる、初心者のうちは便利そうだと思いました
  • @motohiro-mm

    • なにかを削除するときは、それに関連したmodelがないか注意する
      • 親を消した時に子も消す:dependent: :destroy
    • N+1問題対策のbulletというgemがある
    • form_withのときはlocal: trueだったが、link_toremote: trueらしい…
      • rails-ujsでAjaxを利用する話
    • コントローラの粒度の話はなかなか難しかったです
    • 最近のGoogle等を使ったログイン認証が多い理由
      • ユーザー側がID,passwordをたくさん覚えずに済む
      • アプリ側がID,passwordを保管せずに済む

Select a repo