今回はRuboCop1.23からOpenStructの使用を監視するCopが追加されたことについて簡単にまとめたいと思います。Ruby3.0でOpenStructの使用が非推奨になったため、RuboCopがその方針に則った形になります。
OpenStructとは
OpenStructとは、要素を動的に追加・削除ができるクラスです。
要素を動的に追加・削除できる手軽な構造体を提供するクラスです。
OpenStruct のインスタンスに対して未定義なメソッド x= を呼ぶと、 OpenStruct クラスの BasicObject#method_missing で捕捉され、そのインスタンスにインスタンスメソッド x, x= が定義されます。この挙動によって要素を動的に変更できる構造体として働きます。参照: class OpenStruct
使用例としては以下のようになります。
まずは以下のように構造体を作成し、その構造体に要素を追加していきます。
require 'ostruct'
# 構造体(OpenStruct)を作成
user = OpenStruct.new
# 作成した構造体に要素を追加
user.name = "田中太郎"
user.height = 180
user.weight = 65
user.age = 25
ここで試しにuserを出力させてみると、以下のようなオブジェクトが生成されていることが分かります。先ほど追加した要素がオブジェクト内に格納されていますね。
p user
=> #<OpenStruct name="田中太郎", height=180, weight=65, age=25>
追加した要素はメソッドチェーンすることでアクセスできます。
p user.name
=> "田中太郎"
p user.height
=> 180
p user.weight
=> 65
p user.age
=> 25
初期化時にはハッシュを渡すこともできます。
require 'ostruct'
# 初期化時にハッシュを渡す
user = OpenStruct.new({ :name => "山田花子", :age => 20 })
# 要素を取り出す
user.name
=> "山田花子"
user.age
=> 20
Ruby3.0で警告対象になった

OpenStructにはパフォーマンス面、バージョンの脆弱性、潜在的なセキュリティ問題を秘めていることから、Ruby3.0からOpenStructの使用は警告対象になりました。
ちなみにですが、Ruby3.0ドキュメント(OpenStruct)の最後にはOpenStructを使用しないでくださいと強く書かれています。
For all these reasons, consider not using OpenStruct at all.
RuboCop1.23での対応

2021/11/15にリリースされたRuboCop1.23では、OpenStructの使用を監視するCopが追加されました。既にOpenStructを使用しているプロジェクトでは、以下のように修正対応する必要があります。
# bad
point = OpenStruct.new(x: 0, y: 1)
# good
Point = Struct.new(:x, :y)
point = Point.new(0, 1)
# also good
point = { x: 0, y: 1 }
# bad
test_double = OpenStruct.new(a: 'b')
# good (assumes test using rspec-mocks)
test_double = double
allow(test_double).to receive(:a).and_return('b')
すぐの修正対応が困難の場合は、一旦disableするでも良いと思います。
OpenStruct.new(x: 0, y: 1) # rubocop:disable Style/OpenStructUse
まとめ
- OpenStructとは、要素を動的に追加・削除ができるクラス
- OpenStructの初期化時にはハッシュを渡すこともできる
- Ruby3.0からOpenStructの使用は警告対象になった
- RuboCop1.23ではOpenStructの使用を監視するCopが追加された
参考
- class OpenStruct
- class OpenStruct Caveats
- RuboCop Releases
- Consider flagging all uses of OpenStruct #10206
今回はRuboCop1.23からOpenStructの使用を監視するCopが追加されたことについて簡単にまとめました。OpenStructを使用している箇所があれば見直してみてください。