🐕
Ruby の require と $LOADED_FEATURES
Ruby では別の Ruby スクリプトファイルを呼び出すときに require メソッドを利用してそのファイルを読み込みます。
# csv を読み込んで機能が利用できる状態にする
require "csv"
この require メソッドなのですが通常は1度読み込まれた Ruby のスクリプトファイルは2度読み込まれることはありません。
# 1度目のみ csv ファイルが読み込まれる
require "csv"
# いずれかのタイミングでもう一度 require されても csv が再度読み込まれることはない
require "csv"
また require は
- 読み込みを行った場合は
true - 読み込みを行わなかった場合は
false
を返します。
pp require "csv" # => true
pp require "csv" # => false
$LOADED_FEATURES
$LOADED_FEATURES は require でロードされたファイル名の配列になります。
pp $LOADED_FEATURES
# => ["enumerator.so",
# "thread.rb",
# "fiber.so",
# "rational.so",
# "complex.so",
# "ruby2_keywords.rb",
# ...
# ]
require されるとこの配列にそのファイル名が追加されます。
# require 前は含まれないが
pp $LOADED_FEATURES.any? { _1 =~ /csv/ }
# => false
require "csv"
# require 後には require したファイルが含まれるようになる
pp $LOADED_FEATURES.any? { _1 =~ /csv/ }
# => true
$LOADED_FEATURES から要素を削除するとどうなる?
$LOADED_FEATURES から特定の要素を削除すると『それがまだ require されていない』ような振る舞いになります。
require "csv"
# 2回目はロードされない
pp require "csv" # => false
# $LOADED_FEATURES から csv 関連のファイルを削除する
$LOADED_FEATURES.reject! { _1 =~ /csv/ }
# csv が再度ロードされる
pp require "csv" # => true
こんな感じで強制的に再度 require してファイルが読み込まれます。
Rails の Zeitwerk はこの仕組みを利用して再ロードを実現しています。
Discussion