Railsアプリケーションの異なるモジュール(グローバル名前空間/名前空間なしと「Foo」)に同じ名前(「Bar」)の2つのクラスがあるとします。両方のクラスはそれぞれ「app/models/bar.rb」または「app/models/foo/bar.rb」に存在するため、レールによって自動ロードされます。
# "app/models/foo/bar.rb"
module Foo
class Bar
def self.some_method
end
end
end
# "app/models/bar.rb"
class Bar
end
Foo 名前空間に、クラス メソッドで Bar クラスを使用する別のクラスがあります。
module Foo
class Qux
class << self
def something
Bar.some_method # This raises a NoMethod error because
# it uses the Bar defined in the global namespace
# and not the one in Foo
end
end
end
end
name
Rails オートローディングは、シングルトン クラスにある現在の classes を使用して Bar をロードしようとしnil
、デフォルトは "Object" です。
klass_name = name.presence || "Object" # from active_support/dependencies.rb
これにより、RailsBar
は "app/models/foo/bar.rb" ではなく "app/models/bar.rb" からロードされます。thenで定義するQux.something
と、nil ではなく "Foo::Qux" になり、オートロードは正しく機能します。def self.something
.name
現時点では、この問題を回避するための 3 つのオプションがあります。
1) いずれかのBar
クラスの名前を変更する
2)self.
どこでも構文を使用する 3)どこでも明示的に
名前空間Bar
を使用するFoo::Bar
次の理由から、これらのオプションはどれも好きではありません。
1)Bar
はまさに最適な名前です
2)class << self
それ自体はまったく問題なく、ほとんどの Ruby 開発者が使用しているため、次の貧しい人がすぐに同じ問題に遭遇する可能性が高くなります
3) 2) と同じです。根底にある「問題」を実際に修正しないと、誰かが将来、自分のコードが期待どおりに機能しない理由を理解するために時間を無駄にするでしょう.
あなたが考えることができる別のより良いオプションはありますか?