RSpec: 含まれているモジュールではメソッドのみが利用可能になり、定数は利用できないのはなぜですか?
概要
テスト スイート全体の単体テストで使用したい定数を含むモジュールがあります。
私が理解できないのは、モジュールを含めると定数が使用できないのに、メソッド (モジュールに追加した場合) が使用できる理由です。
例:
module Namespace
module Constants
K = 1
def mymethod; end
end
end
describe Namespace::Subject do
include Namespace::Constants
context "Context" do
it "should execute" do
mymethod # succeeds
K # fails
end
end
end
同じ原則がコンソールでも機能します。
2.5.5 :008 > include Namespace::Constants
=> Object
2.5.5 :010 > K
=> 1
解決策
名前空間内で定義された定数は、名前空間内から定数を先頭に置くことで呼び出すことができます。継承は、それが定義されているレベルで行われます。新しいモジュールまたはクラスにメソッドを含める場合、それらのメソッドは、定義されているオブジェクト レベルで呼び出すことができます。
K が Ruby コンソール内で機能したのは、それらをデフォルトまたはグローバル スコープに含めたためです。たとえばこれを実行した場合は、異なる結果が得られるでしょう。
class A
include Namespace::Constants
end
K
NameError: uninitialized constant K
A::K
=>1
a = A.new
a.class::K
=>1
これも説明できる仕様です
require 'pry'
module Namespace
module Constants
def mymethod; end
K = 1
end
end
module Namespace
module Subject
include Namespace::Constants
end
end
class A
include Namespace::Constants
end
describe Namespace::Subject do
describe 'Inherited Constants' do
it 'is defined module level' do
# Check if K is defined at the class level
expect(Namespace::Subject.const_get(:K)).to eq(1)
expect(Namespace::Subject::K).to eq(1)
end
end
end
describe A do
describe 'instance methods' do
it 'defines mymethod' do
a = A.new
expect(a).to respond_to(:mymethod)
end
end
describe 'inherits' do
it 'inherits class definitions' do
expect(A::K).to eq(1)
end
end
end
describe 'Global Scope' do
it 'K is not defined' do
include Namespace::Constants
begin
K
rescue NameError => e
puts e
end
end
end
これが Ruby での継承の仕組みを説明できれば幸いです。あなたが直面している問題は、Rspec 自体とは何の関係もありません。