Ruby Weekly #461: 日本語サマリー
Highlights
Artichoke という mruby ベースのインタープレターのコードをブラウザーで実行してみることができるページ。
Rails 6 RC2 がリリースされた。ファイナルリリースは数週後の予定。
Articles & Tutorials
ヘルパーからバリューオブジェクトを抽出する方法。
Ruby の Infinity オブジェクトいろいろ。
- 0 で割った挙動いろいろ
- 無限 Range(+ Ruby 2.6 の新しい表記)
Rails 6 の ActiveRecord の optimizer_hints
メソッドでクエリ軽量化ヒントを与えれるようになる。
Moving From Tagging with ActsAsTaggableOn to PostgreSQL Arrays
acts-as-taggable-on gem から PostgreSQL 配列カラムに移行した経験談。ネタバレ:migration だけでいけた!
Active Storage 導入手順。
デプロイ失敗の未然防止策。
concurrently
オプションを指定しなかったadd_index
がエラーを起こすように prepend することで、DB をロックする migration 防止rails server
起動時の FK チェックで、CASCADE による重大レコード削除防止Net::HTTP
への prepend で長い HTTP リクエストをタイムアウトさせる
配列であるかどうかの分岐を省略してくれる ActiveSupport の Array.wrap
。
How Do You Tell Which Areas of a Project's Test Suite Need Attention?
所属していないプロジェクトのテストを重点的改善する方法。
- テストスメル特定
- テストがない
- 難解テスト
- テストの重複
- チームに辛いところを聞き出す
- コード弄ってみる
Code and Tools
位置情報用 gem。
関数型 Ruby の副作用を隔離してくれる gem。
Ruby Weekly #459: 日本語サマリー
Highlights
regexp-examples: Generate Strings That Match a Given Regular Expression
正規表現に一致する文字列を生成する gem。Regexp
に #examples
#random_example
メソッドを生やす。
Rails モノリスを ROM マイクロサービスに分解した Aircall 社が ActiveRecord と ROM を比較した記事。
- ActiveRecord の多岐に渡る責務 vs ROM の明確に分けた責務
- ActiveRecord の疑問はググり放題 vs ほとんど ROM フォーラムで聞くことが多い
Lefthook, Crystalball, and Git Magic for a Smooth Development Experience
開発効率化案いろいろ。
- lefthook で git hook 管理・チームと共有。push 前にテストを実行するフック登録。
- crystallball で修正した差分のテストのみに絞る。
- checkout 時に足りてない gem を自動的に
bundle install
するフック登録。 - checkout 時に migration を自動的に実行するフック登録。
Articles & Tutorials
メンテされなくなった PJAX を Turbolinks に移行した Honeybadger 社の注意点。
- Turbolinks は SPA なので、遷移するたびに、ロードしたものをアンロードする必要がある
- 破壊的リクエストを発行するたびにキャッシュをクリアする必要がある
- 遷移した時点の DOM がその状態のままでキャッシュされるから、またそのページに戻ったら状態が初期化されてない覚悟を
<body>
内 JS を全部削除しないと、遷移するたびに実行されちゃう- 外部ライブラリを JS モジュールでインポートすること
- デプロイを跨いだ遷移は古い JS・CSS に依存したままなので、
data-turbolinks-track
属性で強制リロード
Rails ビューで Date
Time
の #strftime
を直接呼ぶのをやめようという主張。 %Y-%m-%d
表記が読みにくいから。 #to_s(:symbol)
で書こうと。 :symbol
は Rails デフォのものからも選べれば、 Date::DATE_FORMATS[:symbol]
`Time::DATE_FORMATS[:symbol] で独自定義もできる。
Minimum Viable Example of Calling Rust From Ruby without a Gem
RSpec コアチームの Sam Phippen 先生が gem なしで Rust を Ruby から呼んだ話。
既存 Rails アプリに devise_token_auth gem を導入する手順。
SQL コメントを書く ActiveRecord::Relation#annotate
が Rails 6 に登場。
Rails での Mysql2::Error: Lock wait timeout exceeded; try restarting transaction
エラーの原因を突き止めた話。
50 秒以上かかるトランザクションがあるときに発生するエラーだが、そのトランザクションがどこにあるのかが謎。 ActiveRecord::Base.transaction
のモンキーパッチで 50 秒以上かかるトランザクションをログに書き込むことで、犯人の正体が暴けた。トランザクション内でメールを送信する処理だった(非同期で送信してなかった)。
Dynamic Image Resizing with Ruby and the Serverless Framework
S3 上画像のサムネなどを Serverless フレームワークで生成する手順。Lambda 関数は Ruby、画像処理は MiniMagick gem で。
Code and Tools
定期イベントを表すオブジェクト用 gem。オブジェクトをシリアライズすることで永続化できる。
WebAssembly 実行用 gem。
メールアナリティックス用 gem。送信・開封・クリック履歴、UTM タグ付けなどの機能付き。
proc を関数型っぽく書く gem。
Sinatra アプリの初期プロジェクト。clone して拡張していくもの。
pg_search: Build ActiveRecord Named Scopes using Postgres's Full Text Search
PostgreSQL 全文検索の複雑な SQL 用 scope
を生やしてくれる gem。なお Solr が提供してくれる機能もいくつか実装してる。 ü
などの発音区別符号を無視する機能とか。
Ruby Weekly #458: 日本語サマリー
Highlights
strong_password gem がハイジャックされた。メンテナが 2 段階認証を有効にしてなかったせいか、rubygems アカウントが乗っ取られちゃった。
問題の v0.0.7 は yank 済み。
時間計算 gem。ActiveSupport と違って、Fixnum などをモンキーパッチしてなくて、依存が少ない。
Rails 6 エラー画面の良いところ
- 例外、絶対パス、エラーメッセージが分かりやすく表示される
- 発生箇所のソースが分かりやすく表示される
- スタックトレースが分かりやすく表示される
- パラメータなど分かりやすく表示される
- ブラウザー内 REPL!!!
良くないところ
Did you mean?
が当たらないことがある。初心者がこいつに惑わされそう。#<#<Class::0x000000000ed0aee0>:0x000000000ed110b0>
といった出力が役立たず
Rails 6 Adds Hooks to Active Job Around Retries and Discards
ActiveJob の retry_on
、discard_on
マクロに渡すブロックは、Rails 6 以降 ActiveSupport::Notifications
フックで書けるようになる。
enqueue_retry.active_job
retry_stopped.active_job
discard.active_job
ApexCharts.rb: Interactive, Responsive Web Charts for Ruby Apps
JS チャート・グラフ用 gem。apexcharts.js ライブラリをラッピングしてるもの。
Articles & Tutorials
Discovering the Design Pattern at the Heart of Rack Middleware
Rack ミドルウェアをデザパタとして定義してる記事。(GoF デザパタ本には載ってないので新規提案)
応用例:
My Experience Architecting A Software Development Stack with JRuby, OpenJDK, and Roda
JRuby + Roda + Sequel + Puma + H2 データベース + いろんな Java ライブラリでレトロゲーム管理システム開発経験談。
JRuby メンテナー Charles Nutter 先生が「高スループット Ruby エンドポイントのベスト実装例」と賞賛するつぶやきでこの記事をバズらせた。
AnyCable を Capistrano + systemd でデプロイする手順。
AnyCable はパフォーマンス・安定性・スケーラビリティが ActionCable に勝るが、Capistrano でデプロイすることは安易ではない。
Grape vs Rack vs Rails の HTTP ヘッダー処理比較。
attr_encrypted などのデカい外部 gem に依存せずに、Rails の ActiveSupport::MessageEncryptor
だけで機密情報を暗号化する方法。
vcr gem を効率よく使う豆知識 10 点。
- cassette 名自動生成しよう
vcr_mode = :once
。あとヘッダー無視しよう- 外部へのリクエスト遮断しよう
- 環境変数で cassette 上書き
VCR.current_cassette.file
- vcr を使ってるテストでは FactoryBot の sequence を必要に応じて固定化しよう
- cassette が何回でも作れるように、テスト冪等化しよう
- 実行順、キャッシュは要注意
- cassette 内 URL 正規化しよう
- cassette 変更時の差分は無視して良し
Building Messaging Between Ruby/Rails Applications with ActiveMQ
Rails の非同期処理を ActiveMQ で実装した経験談。
STOMP プロトコルは stomp gem で対応。本番は AmazonMQ で。
TDD の壁とその乗り越え方。
- 結合テストなどの高レベルテストが落ちる原因が分かりづらい場合は、モデルなどの低レベルテストでテスト書こう。
- モックが多すぎるテスト = 関心ごとが多すぎるテストなので、高レベルテスト書いてから、リファクターしよう。
- context などのネストが深すぎて読み解けないテストは、context・before・shared_context などのコードを it/specify で書き写そう。理解できたら、元のテスト or it/specify のみのテストのどちらかだけ採用。
- テストがそもそもない場合は、現行挙動のテストを書こう。
- テストをどう書くか分からない = 仕様を理解し切れてない。仕様を聞こう or 既存コード調査しよう。
- テスト書く時間がない場合、正常ケースのテストとか低レベルテストだけでも重点的に書こう。
コードレビューで聞く質問集
コードレビュー中には、どこを見ればいいんだっけ、ってよくなりますので、 まとめておきました 英語でまとめたものを日本語に訳しました。
- この PR の目的は何なの?
- PR 作成者がこの PR に到るまでの調査結果・決定事項・仮説は妥当か?
- もっといい解決方法はないか?コード修正以外の解決方法も検討。
- この PR は根本的な解決?それとも暫定対応?暫定対応の場合は、PR 作成者に根本的な解決の計画を立ててもらう。
- この変更点はステークホルダーにどんな影響を与えるか?ステークホルダーはエンドユーザだけでなく、チームメンバーとかも含まれてる。
- その影響は最小限に抑えられないか?
- 影響を最小限に抑えるには、具体的にどんなステップを取るか?
- この PR の動作は正しいか?(言うまでもない)
- 足りてないエッジケースはないか?
- セキュリティの穴はないか?
- コードをもっと読みやすくできないか?
- コードをもっと簡潔に書けないか?
- 削除できる不要なコードはないか?
- PR 作成者にもしものことがあったら、レビュワーである あなた はこのコードを引き継ぐ責任は取れるか?
- マージ前後にやることはないか?特に CI やチームメンバーの開発環境に影響を与える修正。
- オンラインメンテでデプロイできそうか?
- デプロイ前後にやることはないか?PR 作成者にチェックリストを書いてもらう。
下記項目は基本確認しないようにしている。
- コード規約・フォーマット。Rubocop などのリンターに任せましょう。
- テスト。上記項目の確認がぜーんぶ終わったら、テストまで確認する気がほとんど失せてるから。
ポジティブなコメントも欠かさず
レビューに慣れてない人は最初 レビュー = 間違い探し
と思いがち、ネガティブな指摘しか書かない。問題点が見つからなかった PR も「何か書かなきゃ!」というプレッシャー感じて、些末な nits 書いちゃったりする。そういうときは
- どんな状態からどんな状態に変わったか?良い方向に変わった場合は褒める。読みやすくなったことだけでも。レビューしやすく工夫してくれたことでも。
- コード読んで理解したことを文章化する。理解に時間がかかったときは特に文章化する価値がある。認識の確認にもなる。
このレビュー術は、Aiming で培ってきたものです。
エンジニアの CS 対応メモ
この間、CS からのお問い合わせ対応のやり方について新卒に説教することになりました。 せっかくなので書き落としておきました。
手順は
- 何の問題なのか完全に理解すること
- 不明な場合は、お客様に聞くように CS 担当者に依頼すること。
- 必要があればスクショ撮ってもらう。
- 再現すること(できれば)
- リクエストログが追えれば、追うこと
- 本当にその現象が起きた証拠を集めて参考にするために。その中にある情報で何かが分かるかもしれないから。あと人聞き悪いですが、クレーマーが嘘を付くことがたまにある。
- 原因調査すること
- 解決すること
- CS 担当者に連絡すること
- 砕けた文章で OK。お客様向け文章を書くのは CS 担当者の仕事なので。
- 五月雨式の連絡を避けて、出来るだけ連絡内容をまとめてから投げる。
- お客様に何回も連絡すると、お客様がめんどくさくなる。
- CS 担当者の負担を増やさないように。エンジニアを理不尽なクレーマーから守ってるのは CS 担当者だから。
Rails Needs Active Deployment: 日本語サマリー
先週の Ruby Rogues ポッドキャストで取り上げられた熱い記事。
Active Storage、Active Job、Action Cable、Action Mailbox で超楽になってきたが、デプロイという難関が未だに残ってる。Heroku だと簡単に出来ちゃうけど、それ以外はハードルがかなり上がる。
初心者がやり方ググっても、大量のチュートリアルが出て来て、どれも微妙に違ってて結局自分で大量の決断をすることになり、標準化されてなくて保守しづらいインフラが生まれてくる。
Docker は一見簡単だけど、チュートリアルが大量にありすぎて、ほとんど中途半端かつ開発環境に特化した手順にすぎない。
社内にインフラのプロがいなくても、エンジニアが一人で簡単に本番環境構築できるのは Rails 流ではないでしょうか?Convention over configuration で標準化したデプロイできる Active Deployment 的なものニーズは十分ある。コミュニティで実装方法を議論しましょう。
という主張論の記事。
インフラが怖いと思っている僕はものすごく同感。非現実的だという反論はあるとはいえ。(Ruby Rogues でも実際この点でプチ喧嘩にもなった)
Growing Rails Applications in Practice: 日本語サマリー
読破しましたのでサマリー書いておきました。
- コントローラの設計を標準化せよ
- ユーザーの各インタラクションをCRUDリソースで表現せよ
- コントローラの責務は4つのみ
- 認証
- パラメータのパースとホワイトリスト
- モデルのロード
- ビュー指定
- モデルのAPIをvalidation、コールバックで表現
- ActiveModel のモデル積極的に作れ
- クラス切り出してロジック整理せよ
- ファットモデルをダイエットさせてスリムモデル切り出せ
- インタラクションロジックをフォームオブジェクトに切り出せ
- 他オブジェクトモデルから呼ばれる、Active Recordを必要としない単一責務POROのサービスオブジェクトをきり出せ
- モジュールの使い道はファイル構造化のみ
- モデルを積極的にネームスペース・サブフォルダに配置せよ
- CSSはBEMで整理せよ
- 生きたスタイルガイドを用意せよ
- Railsバージョンアップせよ
- Edgeは2〜3パッチレベル成長するまではバージョンアップするな
- モンキーパッチ、gemが多ければ多いほどバージョンアップのコストが高くなる
- 単体テスト、結合テスト書け
- テスト駆動設計せよ