word_wrap が nil を受け取った際に空文字列を返すよう修正
Rails のテキストヘルパー word_wrap が nil を渡されたときに NoMethodError を起こしていた問題を、空文字列を返すように修正しました。これにより、他のテキストヘルパーと同様に nil 安全な呼び出しが可能になります。
背景
word_wrap はビューで長文を折り返す便利メソッドですが、引数が nil の場合に text.empty? が呼び出され NoMethodError が発生していました。実際のコードでは return +"" if text.empty? というガードだけがあり、nil に対するチェックが欠如していました。同一モジュールの truncate、highlight、simple_format、excerpt などはすべて nil を受け入れ、適切な値(nil または空文字列)を返す実装となっており、word_wrap だけが例外を投げる例外的存在でした。したがって、nil が渡されても例外が起きないようにすることが求められました。
この不整合は、ビューでモデル属性が NULL の場合やオプションパラメータが未設定の場合に word_wrap(@post.summary) と記述するとアプリケーションがクラッシュする原因となっていました。テストでも word_wrap(nil) が失敗していることが確認され、実運用でのリスクが顕在化していました。修正により、全テキストヘルパーが同一の nil 耐性を示すようになります。
技術的な変更
この問題は word_wrap の冒頭ガードに nil 判定を追加するだけで解決しました。具体的には return +"" if text.empty? を return +"" if text.nil? || text.empty? に置き換え、nil が渡されたときに即座に空文字列を返すようにしています。
@@ -325,7 +325,7 @@ def word_wrap(text, line_width: 80, break_sequence: "\n")
- return +"" if text.empty?
+ return +"" if text.nil? || text.empty?
さらに、テストスイートに word_wrap が nil を受け取ったケースを検証するテストを追加しました。追加されたテストは assert_equal "", word_wrap(nil) と assert_equal "", word_wrap(nil, line_width: 3) の2パターンを確認し、修正前は NoMethodError が発生し、修正後は期待通り空文字列が返ることを保証します。これにより、コード変更の正当性が自動的に検証されます。
この変更は既存の文字列処理ロジックに影響を与えず、nil 判定だけを追加した最小限の差分です。word_wrap が返す型は従来通り文字列であり、後方互換性は完全に保たれています。
設計判断
判定に nil? を使用し、blank? ではなく nil のみを対象とした点が重要です。blank? を使うと空白文字列(例: " ")も true と判定され、折り返し対象から除外される可能性がありますが、今回の変更では空白文字列は従来通り折り返し処理の対象としたいという意図が保たれています。
word_wrap 以外のテキストヘルパーはそれぞれ nil に対して例外を出さずに nil、空文字列、あるいは HTML 文字列を返す実装となっており、今回の修正で API の一貫性が確保されました。nil が安全に扱えるようになったことで、ヘルパー群全体の使用感が統一され、開発者が個別に nil チェックを書く必要がなくなります。
この設計判断は、最小限のコード変更で既存の振る舞いを壊さずに安全性だけを向上させるという Rails の設計方針に沿ったものです。
まとめ
word_wrap が nil を安全に受け取れるようになり、ビューで NULL 属性やオプションパラメータを直接渡すケースでも例外が発生しなくなります。既存の空文字列処理はそのまま保持され、後方互換性に影響はありません。テキストヘルパー全体の API が一貫した nil 耐性を示すようになり、開発者体験が向上しました。