jeeves 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/jeeves/define_imported_method.rb +56 -0
- data/lib/jeeves/import.rb +27 -0
- data/lib/jeeves/resolve_dependency.rb +1 -5
- data/lib/jeeves/stub_scope.rb +19 -0
- data/lib/jeeves/version.rb +4 -1
- data/lib/jeeves.rb +19 -29
- data/spec/integration/import_spec.rb +32 -7
- data/spec/integration/rspec_spec.rb +16 -1
- data/spec/unit/resolve_callable_spec.rb +0 -2
- data/spec/unit/resolve_constant_spec.rb +0 -2
- data/spec/unit/resolve_dependency_spec.rb +1 -1
- data/spec/unit/resolve_method_spec.rb +0 -2
- metadata +5 -2
@@ -0,0 +1,56 @@
|
|
1
|
+
module Jeeves
|
2
|
+
class DefineImportedMethod
|
3
|
+
def call(target, internal_name, options)
|
4
|
+
@target = target
|
5
|
+
@internal_name = internal_name
|
6
|
+
@scope = options.fetch(:from)
|
7
|
+
@external_name = options.fetch(:name)
|
8
|
+
if options[:lazy] == true
|
9
|
+
define_lazy
|
10
|
+
elsif options[:lazy] == false
|
11
|
+
define_non_lazy
|
12
|
+
else
|
13
|
+
define_smart
|
14
|
+
end
|
15
|
+
define_on_instance
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def define_lazy
|
21
|
+
scope = @scope
|
22
|
+
external_name = @external_name
|
23
|
+
@target.class.send(:define_method, @internal_name) do |*args, &block|
|
24
|
+
delegator = ResolveDependency.call(scope, external_name)
|
25
|
+
delegator.call(*args, &block)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def define_non_lazy
|
30
|
+
delegator = ResolveDependency.call(@scope, @external_name)
|
31
|
+
@target.class.send(:define_method, @internal_name) do |*args, &block|
|
32
|
+
delegator.call(*args, &block)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def define_smart
|
37
|
+
scope = @scope
|
38
|
+
internal_name = @internal_name
|
39
|
+
external_name = @external_name
|
40
|
+
@target.class.send(:define_method, @internal_name) do |*args, &block|
|
41
|
+
delegator = ResolveDependency.call(scope, external_name)
|
42
|
+
self.class.send(:define_method, internal_name) do |*args, &block|
|
43
|
+
delegator.call(*args, &block)
|
44
|
+
end
|
45
|
+
delegator.call(*args, &block)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def define_on_instance
|
50
|
+
internal_name = @internal_name
|
51
|
+
@target.send(:define_method, internal_name) do |*args, &block|
|
52
|
+
self.class.send(internal_name, *args, &block)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Jeeves
|
2
|
+
class Import
|
3
|
+
def call(target, *args)
|
4
|
+
@target = target
|
5
|
+
parse_options(args)
|
6
|
+
@names.each do |external_name, internal_name|
|
7
|
+
DefineImportedMethod.new.call(target, internal_name, from: @scope,
|
8
|
+
name: external_name, lazy: @lazy)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def parse_options(args)
|
15
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
16
|
+
@names = args.map { |name| name.is_a?(Array) ? name : [name, name] }
|
17
|
+
@scope = options.fetch(:from) { default_scope }
|
18
|
+
@lazy = options.fetch(:lazy, :smart)
|
19
|
+
end
|
20
|
+
|
21
|
+
def default_scope
|
22
|
+
module_names = @target.ancestors.first.to_s.split('::')[0..-2]
|
23
|
+
module_names.inject(Object) { |m, c| m.const_get(c) }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
@@ -10,16 +10,12 @@ module Jeeves
|
|
10
10
|
RESOLVERS.each do |resolver|
|
11
11
|
break if delegator = resolver.call(scope, name)
|
12
12
|
end
|
13
|
-
delegator = mock(delegator, scope, name) if in_test_framework?
|
13
|
+
delegator = mock(delegator, scope, name) if Jeeves.in_test_framework?
|
14
14
|
delegator or unresolved(scope, name)
|
15
15
|
end
|
16
16
|
|
17
17
|
private
|
18
18
|
|
19
|
-
def self.in_test_framework?
|
20
|
-
defined?(RSpec) || defined?(Test::Unit)
|
21
|
-
end
|
22
|
-
|
23
19
|
def self.mock(delegator, scope, name)
|
24
20
|
lambda do |*args, &block|
|
25
21
|
if Jeeves.respond_to?(name)
|
data/lib/jeeves/version.rb
CHANGED
data/lib/jeeves.rb
CHANGED
@@ -1,36 +1,26 @@
|
|
1
1
|
module Jeeves
|
2
|
-
autoload :
|
3
|
-
autoload :
|
4
|
-
autoload :
|
5
|
-
autoload :
|
2
|
+
autoload :Import, "jeeves/import"
|
3
|
+
autoload :ResolveDependency, "jeeves/resolve_dependency"
|
4
|
+
autoload :ResolveMethod, "jeeves/resolve_method"
|
5
|
+
autoload :ResolveCallable, "jeeves/resolve_callable"
|
6
|
+
autoload :ResolveConstant, "jeeves/resolve_constant"
|
7
|
+
autoload :DefineImportedMethod, "jeeves/define_imported_method"
|
8
|
+
autoload :StubScope, "jeeves/stub_scope"
|
6
9
|
|
7
10
|
def import(*args)
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
else
|
17
|
-
external_name = internal_name = name
|
18
|
-
end
|
19
|
-
if options[:lazy]
|
20
|
-
self.class.send(:define_method, internal_name) do |*args, &block|
|
21
|
-
delegator = ResolveDependency.call(scope, external_name)
|
22
|
-
delegator.call(*args, &block)
|
23
|
-
end
|
24
|
-
else
|
25
|
-
delegator = ResolveDependency.call(scope, external_name)
|
26
|
-
self.class.send(:define_method, internal_name) do |*args, &block|
|
27
|
-
delegator.call(*args, &block)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
define_method(internal_name) do |*args, &block|
|
31
|
-
self.class.send(internal_name, *args, &block)
|
32
|
-
end
|
11
|
+
Import.new.call(self, *args)
|
12
|
+
end
|
13
|
+
|
14
|
+
def const_missing(name)
|
15
|
+
if Jeeves.in_test_framework?
|
16
|
+
StubScope.call(name)
|
17
|
+
else
|
18
|
+
super
|
33
19
|
end
|
34
20
|
end
|
21
|
+
|
22
|
+
def self.in_test_framework?
|
23
|
+
defined?(RSpec) || defined?(Test::Unit)
|
24
|
+
end
|
35
25
|
end
|
36
26
|
|
@@ -29,10 +29,15 @@ module JeevesTestApp
|
|
29
29
|
class TestSubject
|
30
30
|
extend Jeeves
|
31
31
|
import :my_method, :my_callable, :my_constant, from: OtherScope
|
32
|
-
import :marco, :static_callable
|
32
|
+
import :marco, :static_callable, lazy: false
|
33
33
|
import :lazy_method, lazy: true
|
34
|
+
import :smart_resolver
|
34
35
|
import [:marco, :say_polo]
|
35
36
|
end
|
37
|
+
|
38
|
+
def self.smart_resolver
|
39
|
+
:acts_smart
|
40
|
+
end
|
36
41
|
end
|
37
42
|
end
|
38
43
|
|
@@ -63,8 +68,10 @@ describe "import" do
|
|
63
68
|
end
|
64
69
|
|
65
70
|
it "resolves lazy dependencies at call time" do
|
66
|
-
JeevesTestApp::InnerScope.stub(:lazy_method) { :
|
67
|
-
subject.lazy_method.should == :
|
71
|
+
JeevesTestApp::InnerScope.stub(:lazy_method) { :snooze1 }
|
72
|
+
subject.lazy_method.should == :snooze1
|
73
|
+
JeevesTestApp::InnerScope.stub(:lazy_method) { :snooze2 }
|
74
|
+
subject.lazy_method.should == :snooze2
|
68
75
|
end
|
69
76
|
|
70
77
|
it "resolves non-lazy dependencies at import time" do
|
@@ -72,6 +79,12 @@ describe "import" do
|
|
72
79
|
subject.marco.should == :polo
|
73
80
|
end
|
74
81
|
|
82
|
+
it "defaults to resolving dependencies once at first call" do
|
83
|
+
subject.smart_resolver
|
84
|
+
JeevesTestApp::InnerScope.stub(:smart_resolver) { :snooze }
|
85
|
+
subject.smart_resolver.should == :acts_smart
|
86
|
+
end
|
87
|
+
|
75
88
|
it "imports under an alias" do
|
76
89
|
subject.say_polo.should == :polo
|
77
90
|
end
|
@@ -82,10 +95,22 @@ describe "import" do
|
|
82
95
|
end
|
83
96
|
|
84
97
|
it "raises an error if no importers can find the dependency" do
|
85
|
-
Jeeves
|
86
|
-
expect
|
87
|
-
|
88
|
-
|
98
|
+
Jeeves.stub(:in_test_framework?) { false } # to avoid RSpec integration
|
99
|
+
expect do
|
100
|
+
class JeevesTestApp::InnerScope::TestSubject
|
101
|
+
import :unknown, from: JeevesTestApp::OtherScope, lazy: false
|
102
|
+
end
|
103
|
+
end.to raise_error(Jeeves::UnresolvedDependency,
|
104
|
+
"Dependency 'unknown' was not found in JeevesTestApp::OtherScope")
|
105
|
+
end
|
106
|
+
|
107
|
+
it "raises an error if the scope is undefined" do
|
108
|
+
Jeeves.stub(:in_test_framework?) { false } # to avoid RSpec integration
|
109
|
+
expect do
|
110
|
+
class JeevesTestApp::InnerScope::TestSubject
|
111
|
+
import :unknown, from: MyUndefined::Scope, lazy: false
|
112
|
+
end
|
113
|
+
end.to raise_error(NameError)
|
89
114
|
end
|
90
115
|
end
|
91
116
|
|
@@ -9,6 +9,7 @@ module JeevesTestApp
|
|
9
9
|
class TestSubject
|
10
10
|
extend Jeeves
|
11
11
|
import :my_mock, :loaded_dependency
|
12
|
+
import :external_mock, from: MyUndefined::Scope
|
12
13
|
|
13
14
|
def call
|
14
15
|
my_mock(42)
|
@@ -17,6 +18,10 @@ module JeevesTestApp
|
|
17
18
|
def call_integrated
|
18
19
|
loaded_dependency
|
19
20
|
end
|
21
|
+
|
22
|
+
def call_external
|
23
|
+
external_mock
|
24
|
+
end
|
20
25
|
end
|
21
26
|
end
|
22
27
|
end
|
@@ -34,7 +39,7 @@ describe "rspec integration" do
|
|
34
39
|
"Dependency 'my_mock' was not found in JeevesTestApp::InnerScope")
|
35
40
|
end
|
36
41
|
|
37
|
-
it "overrides loaded dependencies with mocked
|
42
|
+
it "overrides loaded dependencies with mocked methods on Jeeves" do
|
38
43
|
Jeeves.stub(:loaded_dependency) { :stubbed_value }
|
39
44
|
subject.call_integrated.should == :stubbed_value
|
40
45
|
end
|
@@ -42,5 +47,15 @@ describe "rspec integration" do
|
|
42
47
|
it "uses loaded dependencies if they are not mocked on Jeeves" do
|
43
48
|
subject.call_integrated.should == :real_value
|
44
49
|
end
|
50
|
+
|
51
|
+
it "treats missing scope as Jeeves" do
|
52
|
+
Jeeves.stub(:external_mock) { :stubbed_value }
|
53
|
+
subject.call_external.should == :stubbed_value
|
54
|
+
end
|
55
|
+
|
56
|
+
it "raises an error if the dependency in missing scope is not mocked" do
|
57
|
+
expect { subject.call_external }.to raise_error(Jeeves::UnresolvedDependency,
|
58
|
+
"Dependency 'external_mock' was not found in MyUndefined::Scope")
|
59
|
+
end
|
45
60
|
end
|
46
61
|
|
@@ -18,7 +18,6 @@ end
|
|
18
18
|
|
19
19
|
module Jeeves
|
20
20
|
describe ResolveCallable do
|
21
|
-
|
22
21
|
it "returns an anonymous function which delegates to the static call method of the callable" do
|
23
22
|
delegator = ResolveCallable.call(JeevesTestApp::CallableTest, :static_callable)
|
24
23
|
result = delegator.call(:foo, :bar, :baz) { |s| s.capitalize }
|
@@ -35,7 +34,6 @@ module Jeeves
|
|
35
34
|
delegator = ResolveCallable.call(JeevesTestApp::CallableTest, :undefined_callable)
|
36
35
|
delegator.should be(nil)
|
37
36
|
end
|
38
|
-
|
39
37
|
end
|
40
38
|
end
|
41
39
|
|
@@ -8,7 +8,6 @@ end
|
|
8
8
|
|
9
9
|
module Jeeves
|
10
10
|
describe ResolveConstant do
|
11
|
-
|
12
11
|
it "returns an anonymous function which returns the constant" do
|
13
12
|
delegator = ResolveConstant.call(JeevesTestApp::ConstantTest, :my_constant)
|
14
13
|
delegator.call.should == "MY VALUE"
|
@@ -18,7 +17,6 @@ module Jeeves
|
|
18
17
|
delegator = ResolveConstant.call(JeevesTestApp::ConstantTest, :undefined_constant)
|
19
18
|
delegator.should be(nil)
|
20
19
|
end
|
21
|
-
|
22
20
|
end
|
23
21
|
end
|
24
22
|
|
@@ -11,7 +11,7 @@ module Jeeves
|
|
11
11
|
let(:delegator) { stub("delegator") }
|
12
12
|
|
13
13
|
before do
|
14
|
-
Jeeves
|
14
|
+
Jeeves.stub(:in_test_framework?) { false } # to avoid RSpec integration
|
15
15
|
ResolveMethod.stub(:call)
|
16
16
|
ResolveCallable.stub(:call)
|
17
17
|
ResolveConstant.stub(:call)
|
@@ -10,7 +10,6 @@ end
|
|
10
10
|
|
11
11
|
module Jeeves
|
12
12
|
describe ResolveMethod do
|
13
|
-
|
14
13
|
it "returns an anonymous function which delegates to the method" do
|
15
14
|
delegator = ResolveMethod.call(JeevesTestApp::MethodTest, :my_method)
|
16
15
|
result = delegator.call(:foo, :bar, :baz) { |s| s.upcase }
|
@@ -21,7 +20,6 @@ module Jeeves
|
|
21
20
|
delegator = ResolveMethod.call(JeevesTestApp::MethodTest, :undefined_method)
|
22
21
|
delegator.should be(nil)
|
23
22
|
end
|
24
|
-
|
25
23
|
end
|
26
24
|
end
|
27
25
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jeeves
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-06-
|
12
|
+
date: 2012-06-20 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
@@ -36,10 +36,13 @@ extensions: []
|
|
36
36
|
extra_rdoc_files: []
|
37
37
|
files:
|
38
38
|
- lib/jeeves.rb
|
39
|
+
- lib/jeeves/import.rb
|
40
|
+
- lib/jeeves/define_imported_method.rb
|
39
41
|
- lib/jeeves/resolve_dependency.rb
|
40
42
|
- lib/jeeves/version.rb
|
41
43
|
- lib/jeeves/resolve_constant.rb
|
42
44
|
- lib/jeeves/resolve_method.rb
|
45
|
+
- lib/jeeves/stub_scope.rb
|
43
46
|
- lib/jeeves/resolve_callable.rb
|
44
47
|
- spec/integration/rspec_spec.rb
|
45
48
|
- spec/integration/import_spec.rb
|