jeeves 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,13 +1,39 @@
1
1
  module Jeeves
2
+ class UnresolvedDependency < StandardError
3
+ end
4
+
2
5
  class ResolveDependency
3
- RESOLVERS = [ResolveMethod, ResolveCallable, ResolveConstant, ResolveMock]
6
+ RESOLVERS = [ResolveMethod, ResolveCallable, ResolveConstant]
4
7
 
5
8
  def self.call(scope, name)
6
9
  delegator = nil
7
10
  RESOLVERS.each do |resolver|
8
11
  break if delegator = resolver.call(scope, name)
9
12
  end
10
- delegator or raise ArgumentError, "Dependency '#{name}' was not found in #{scope}"
13
+ delegator = mock(delegator, scope, name) if in_test_framework?
14
+ delegator or unresolved(scope, name)
15
+ end
16
+
17
+ private
18
+
19
+ def self.in_test_framework?
20
+ defined?(RSpec) || defined?(Test::Unit)
21
+ end
22
+
23
+ def self.mock(delegator, scope, name)
24
+ lambda do |*args, &block|
25
+ if Jeeves.respond_to?(name)
26
+ Jeeves.send(name, *args, &block)
27
+ elsif delegator
28
+ delegator.call(*args, &block)
29
+ else
30
+ unresolved(scope, name)
31
+ end
32
+ end
33
+ end
34
+
35
+ def self.unresolved(scope, name)
36
+ raise UnresolvedDependency, "Dependency '#{name}' was not found in #{scope}"
11
37
  end
12
38
  end
13
39
  end
@@ -1,4 +1,4 @@
1
1
  module Jeeves
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1"
3
3
  end
4
4
 
data/lib/jeeves.rb CHANGED
@@ -3,7 +3,6 @@ module Jeeves
3
3
  autoload :ResolveMethod, "jeeves/resolve_method"
4
4
  autoload :ResolveCallable, "jeeves/resolve_callable"
5
5
  autoload :ResolveConstant, "jeeves/resolve_constant"
6
- autoload :ResolveMock, "jeeves/resolve_mock"
7
6
 
8
7
  def import(*args)
9
8
  options = args.last.is_a?(Hash) ? args.pop : {}
@@ -18,16 +17,19 @@ module Jeeves
18
17
  external_name = internal_name = name
19
18
  end
20
19
  if options[:lazy]
21
- define_method(internal_name) do |*args, &block|
20
+ self.class.send(:define_method, internal_name) do |*args, &block|
22
21
  delegator = ResolveDependency.call(scope, external_name)
23
22
  delegator.call(*args, &block)
24
23
  end
25
24
  else
26
25
  delegator = ResolveDependency.call(scope, external_name)
27
- define_method(internal_name) do |*args, &block|
26
+ self.class.send(:define_method, internal_name) do |*args, &block|
28
27
  delegator.call(*args, &block)
29
28
  end
30
29
  end
30
+ define_method(internal_name) do |*args, &block|
31
+ self.class.send(internal_name, *args, &block)
32
+ end
31
33
  end
32
34
  end
33
35
  end
@@ -76,10 +76,15 @@ describe "import" do
76
76
  subject.say_polo.should == :polo
77
77
  end
78
78
 
79
+ it "also imports into as a class method" do
80
+ result = subject.class.my_method(:foo, :bar, :baz) { |s| s.upcase }
81
+ result.should == "FOO-BAR-BAZ"
82
+ end
83
+
79
84
  it "raises an error if no importers can find the dependency" do
80
- Jeeves::ResolveMock.stub(:call) # to avoid RSpec integration
85
+ Jeeves::ResolveDependency.stub(:in_test_framework?) { false } # to avoid RSpec integration
81
86
  expect { subject.class.import :unknown, from: JeevesTestApp::OtherScope }.
82
- to raise_error(ArgumentError,
87
+ to raise_error(Jeeves::UnresolvedDependency,
83
88
  "Dependency 'unknown' was not found in JeevesTestApp::OtherScope")
84
89
  end
85
90
  end
@@ -2,13 +2,21 @@ require "jeeves"
2
2
 
3
3
  module JeevesTestApp
4
4
  module InnerScope
5
+ def self.loaded_dependency
6
+ :real_value
7
+ end
8
+
5
9
  class TestSubject
6
10
  extend Jeeves
7
- import :my_mock
11
+ import :my_mock, :loaded_dependency
8
12
 
9
13
  def call
10
14
  my_mock(42)
11
15
  end
16
+
17
+ def call_integrated
18
+ loaded_dependency
19
+ end
12
20
  end
13
21
  end
14
22
  end
@@ -22,8 +30,17 @@ describe "rspec integration" do
22
30
  end
23
31
 
24
32
  it "raises an error if the dependency is not mocked" do
25
- expect { subject.call }.to raise_error(ArgumentError,
33
+ expect { subject.call }.to raise_error(Jeeves::UnresolvedDependency,
26
34
  "Dependency 'my_mock' was not found in JeevesTestApp::InnerScope")
27
35
  end
36
+
37
+ it "overrides loaded dependencies with mocked methdos on Jeeves" do
38
+ Jeeves.stub(:loaded_dependency) { :stubbed_value }
39
+ subject.call_integrated.should == :stubbed_value
40
+ end
41
+
42
+ it "uses loaded dependencies if they are not mocked on Jeeves" do
43
+ subject.call_integrated.should == :real_value
44
+ end
28
45
  end
29
46
 
@@ -2,7 +2,6 @@ module Jeeves
2
2
  class ResolveMethod; end
3
3
  class ResolveCallable; end
4
4
  class ResolveConstant; end
5
- class ResolveMock; end
6
5
  end
7
6
  require "jeeves/resolve_dependency"
8
7
 
@@ -12,6 +11,7 @@ module Jeeves
12
11
  let(:delegator) { stub("delegator") }
13
12
 
14
13
  before do
14
+ Jeeves::ResolveDependency.stub(:in_test_framework?) { false } # to avoid RSpec integration
15
15
  ResolveMethod.stub(:call)
16
16
  ResolveCallable.stub(:call)
17
17
  ResolveConstant.stub(:call)
@@ -32,15 +32,9 @@ module Jeeves
32
32
  ResolveDependency.call(scope, :my_dependency).should be(delegator)
33
33
  end
34
34
 
35
- it "uses ResolveMock as a last resort" do
36
- ResolveMock.stub(:call).with(scope, :my_dependency) { delegator }
37
- ResolveDependency.call(scope, :my_dependency).should be(delegator)
38
- end
39
-
40
35
  it "raises an error if all importers fail" do
41
- Jeeves::ResolveMock.stub(:call) # to avoid RSpec integration
42
36
  expect { ResolveDependency.call(scope, :my_dependency) }.
43
- to raise_error(ArgumentError,
37
+ to raise_error(Jeeves::UnresolvedDependency,
44
38
  "Dependency 'my_dependency' was not found in ScopeStub")
45
39
  end
46
40
  end
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.0
4
+ version: 0.2.1
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-16 00:00:00.000000000 Z
12
+ date: 2012-06-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
@@ -27,9 +27,10 @@ dependencies:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
29
  version: '2.8'
30
- description:
31
- email:
32
- - rchopper@gmail.com
30
+ description: Jeeves is a personal valet for your Ruby code. It is used to manage dependencies
31
+ between loosely coupled classes via explicit declaraion. It is _not_ a traditional
32
+ dependency injection framework, although it can easily fill that role.
33
+ email: rchopper@gmail.com
33
34
  executables: []
34
35
  extensions: []
35
36
  extra_rdoc_files: []
@@ -39,7 +40,6 @@ files:
39
40
  - lib/jeeves/version.rb
40
41
  - lib/jeeves/resolve_constant.rb
41
42
  - lib/jeeves/resolve_method.rb
42
- - lib/jeeves/resolve_mock.rb
43
43
  - lib/jeeves/resolve_callable.rb
44
44
  - spec/integration/rspec_spec.rb
45
45
  - spec/integration/import_spec.rb
@@ -48,7 +48,8 @@ files:
48
48
  - spec/unit/resolve_constant_spec.rb
49
49
  - spec/unit/resolve_dependency_spec.rb
50
50
  homepage: http://github.com/ronhopper/jeeves
51
- licenses: []
51
+ licenses:
52
+ - MIT
52
53
  post_install_message:
53
54
  rdoc_options: []
54
55
  require_paths:
@@ -1,22 +0,0 @@
1
- module Jeeves
2
- class ResolveMock
3
- def self.call(scope, name)
4
- if in_test_framework?
5
- lambda do |*args, &block|
6
- if Jeeves.respond_to?(name)
7
- Jeeves.public_send(name, *args, &block)
8
- else
9
- raise ArgumentError, "Dependency '#{name}' was not found in #{scope}"
10
- end
11
- end
12
- end
13
- end
14
-
15
- private
16
-
17
- def self.in_test_framework?
18
- defined?(RSpec) || defined?(Test::Unit)
19
- end
20
- end
21
- end
22
-