Skip to content
This repository was archived by the owner on Nov 30, 2024. It is now read-only.

Commit a9faf8b

Browse files
committed
Merge pull request #76 from jimmycuadra/recursive-const-methods
Move in code from RSpec::Mocks::RecursiveConstantMethods
2 parents 1a03918 + 630fec9 commit a9faf8b

File tree

2 files changed

+127
-0
lines changed

2 files changed

+127
-0
lines changed
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
module RSpec
2+
module Support
3+
# Provides recursive constant lookup methods useful for
4+
# constant stubbing.
5+
module RecursiveConstMethods
6+
# We only want to consider constants that are defined directly on a
7+
# particular module, and not include top-level/inherited constants.
8+
# Unfortunately, the constant API changed between 1.8 and 1.9, so
9+
# we need to conditionally define methods to ignore the top-level/inherited
10+
# constants.
11+
#
12+
# Given:
13+
# class A; B = 1; end
14+
# class C < A; end
15+
#
16+
# On 1.8:
17+
# - C.const_get("Hash") # => ::Hash
18+
# - C.const_defined?("Hash") # => false
19+
# - C.constants # => ["B"]
20+
# - None of these methods accept the extra `inherit` argument
21+
# On 1.9:
22+
# - C.const_get("Hash") # => ::Hash
23+
# - C.const_defined?("Hash") # => true
24+
# - C.const_get("Hash", false) # => raises NameError
25+
# - C.const_defined?("Hash", false) # => false
26+
# - C.constants # => [:B]
27+
# - C.constants(false) #=> []
28+
if Module.method(:const_defined?).arity == 1
29+
def const_defined_on?(mod, const_name)
30+
mod.const_defined?(const_name)
31+
end
32+
33+
def get_const_defined_on(mod, const_name)
34+
if const_defined_on?(mod, const_name)
35+
return mod.const_get(const_name)
36+
end
37+
38+
raise NameError, "uninitialized constant #{mod.name}::#{const_name}"
39+
end
40+
41+
def constants_defined_on(mod)
42+
mod.constants.select { |c| const_defined_on?(mod, c) }
43+
end
44+
else
45+
def const_defined_on?(mod, const_name)
46+
mod.const_defined?(const_name, false)
47+
end
48+
49+
def get_const_defined_on(mod, const_name)
50+
mod.const_get(const_name, false)
51+
end
52+
53+
def constants_defined_on(mod)
54+
mod.constants(false)
55+
end
56+
end
57+
58+
def recursive_const_get(const_name)
59+
normalize_const_name(const_name).split('::').inject(Object) do |mod, name|
60+
get_const_defined_on(mod, name)
61+
end
62+
end
63+
64+
def recursive_const_defined?(const_name)
65+
normalize_const_name(const_name).split('::').inject([Object, '']) do |(mod, full_name), name|
66+
yield(full_name, name) if block_given? && !(Module === mod)
67+
return false unless const_defined_on?(mod, name)
68+
[get_const_defined_on(mod, name), [mod, name].join('::')]
69+
end
70+
end
71+
72+
def normalize_const_name(const_name)
73+
const_name.sub(/\A::/, '')
74+
end
75+
end
76+
end
77+
end
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
require 'spec_helper'
2+
require 'rspec/support/recursive_const_methods'
3+
4+
module RSpec
5+
module Support
6+
describe RecursiveConstMethods do
7+
include described_class
8+
9+
module Foo
10+
class Parent
11+
UNDETECTED = 'Not seen when looking up constants in Bar'
12+
end
13+
14+
class Bar < Parent
15+
VAL = 10
16+
end
17+
end
18+
19+
describe '#recursive_const_defined?' do
20+
it 'finds constants' do
21+
const, _name = recursive_const_defined?('::RSpec::Support::Foo::Bar::VAL')
22+
23+
expect(const).to eq(10)
24+
end
25+
26+
it 'returns the fully qualified name of the constant' do
27+
_const, name = recursive_const_defined?('::RSpec::Support::Foo::Bar::VAL')
28+
29+
expect(name).to eq('RSpec::Support::Foo::Bar::VAL')
30+
end
31+
32+
it 'does not find constants in ancestors' do
33+
expect(recursive_const_defined?('::RSpec::Support::Foo::Bar::UNDETECTED')).to be_falsy
34+
end
35+
end
36+
37+
describe '#recursive_const_get' do
38+
it 'gets constants' do
39+
expect(recursive_const_get('::RSpec::Support::Foo::Bar::VAL')).to eq(10)
40+
end
41+
42+
it 'does not get constants in ancestors' do
43+
expect do
44+
recursive_const_get('::RSpec::Support::Foo::Bar::UNDETECTED')
45+
end.to raise_error(NameError)
46+
end
47+
end
48+
end
49+
end
50+
end

0 commit comments

Comments
 (0)