この記事は?
Ruby の静的コード解析の定番 Gem の RuboCop。そのひとつひとつのルールのことを Cop と呼びます。そして、RuboCop Rails は Rails 向けのルールを RuboCop に追加するための Gem です。
ふと、RuboCop Rails で追加された Cop (ルール) を確認することで、Rails の知らない機能を知るいい機会になるのではと思いました。そこで、試しに 2022/09/09 (金) にリリースされたバージョン 2.16.0 の内容を見てみました
そうすると、案の定知らないことばかりで非常に勉強になりました!そこで、実際にどんな学びがあったかこの記事で共有したいと思います 🙌
例: RuboCop Rails 2.16.0 追加された Cop
#714: Add new Rails/FreezeTime
cop.
-
travel_to メソッドの引数に現在日時を渡す場合は、代わりに freeze_time メソッドを使うべし。
- freeze_time メソッドは Rails 5.2 で追加されました。
- わたしはいつも travel_to を使ってしまっていました
# Bad 🙅
travel_to(Time.now)
travel_to(DateTime.now)
travel_to(Time.current)
travel_to(Time.zone.now)
travel_to(Time.now.in_time_zone)
travel_to(Time.current.to_time)
# Good 🙆
freeze_time
#744: Add new Rails/WhereMissing
cop.
- LEFT JOIN して関連レコードがないレコードに絞り込みたい場合は missing メソッドを使うべし。
- missing メソッドは Rails 6.1 で追加されました。
# Bad 🙅
Post.left_joins(:author).where(authors: { id: nil })
# Good 🙆
Post.where.missing(:author)
#587: Add new Rails/RootPathnameMethods
cop.
- Rails.root.join が返す Pathname オブジェクトを使用してファイルを操作する場合は、File クラスを使わずに Pathname オブジェクトのメソッドを使うべし。
# Bad 🙅
File.open(Rails.root.join('db', 'schema.rb'))
File.open(Rails.root.join('db', 'schema.rb'), 'w')
File.read(Rails.root.join('db', 'schema.rb'))
File.binread(Rails.root.join('db', 'schema.rb'))
File.write(Rails.root.join('db', 'schema.rb'), content)
File.binwrite(Rails.root.join('db', 'schema.rb'), content)
# Good 🙆
Rails.root.join('db', 'schema.rb').open
Rails.root.join('db', 'schema.rb').open('w')
Rails.root.join('db', 'schema.rb').read
Rails.root.join('db', 'schema.rb').binread
Rails.root.join('db', 'schema.rb').write(content)
Rails.root.join('db', 'schema.rb').binwrite(content)
#752: Add Rails/TopLevelHashWithIndifferentAccess
cop.
-
::HashWithIndifferentAccess
は非推奨なので、代わりにActiveSupport::HashWithIndifferentAccess
を使うべし。- Rails 5.1 から非推奨 (soft-deprecated) です。
# Bad 🙅
HashWithIndifferentAccess.new(foo: 'bar')
# Good 🙆
ActiveSupport::HashWithIndifferentAccess.new(foo: 'bar')
#759: Add new Rails/ActionControllerFlashBeforeRender
cop.
-
render
の前で flash メッセージを設定する場合はflash.now
を使うべし。- さもないと、次のアクションまで flash メッセージが意図せず残り続ける場合があります。
- 参考: flashとflash.nowの違いを検証してみた - Qiita
# Bad 🙅
class HomeController < ApplicationController
def create
flash[:alert] = "msg"
render :index
end
end
# Good 🙆
class HomeController < ApplicationController
def create
flash.now[:alert] = "msg"
render :index
end
end
#749: Add new Rails/ActiveSupportOnLoad
cop.
- Rails が提供するクラスにモンキーパッチを当てる場合は ActiveSupport.on_load を使うべし。
- そうすることで遅延読み込みになり、必要になって初めてパッチが読み込まれるようになります。
# Bad 🙅
ActiveRecord::Base.include(MyClass)
# Good 🙆
ActiveSupport.on_load(:active_record) { include MyClass }
#747: Add Rails/ToSWithArgument
cop.
-
to_s(format)
は Rails 7.0 から非推奨であるためです。- Ruby 3.1 で to_s メソッドが最適化されているため、Rails 7.0 ではこのメソッドのオーバーライドを避けて最適化の恩恵を受けるように対応されています。
- 参考: Deprecate
to_s(format)
in favor ofto_formatted_s(format)
by rafaelfranca · Pull Request #43772 · rails/rails · GitHub
# Bad 🙅
obj.to_s(:delimited)
# Good 🙆
obj.to_formatted_s(:delimited)
まとめ
RuboCop Rails の特定のリリース内容を確認して Cop が追加された背景を調べることで、Rails の知らない機能や非推奨な機能を知ることができます。今回の調査はとても有用だと感じたので、今度もバージョン更新のたびにリリース内容を確認していこうと思いました。みなさんもぜひ、気が向いたときに確認してみてくださいね