collaborator 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.0.2
data/collaborator.gemspec CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "collaborator"
8
- s.version = "0.0.1"
8
+ s.version = "0.0.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Sebastian Porto"]
data/lib/collaborator.rb CHANGED
@@ -1,24 +1,36 @@
1
1
  module Collaborator
2
2
 
3
- def self.included(base)
4
- base.extend(ClassMethods)
3
+ # a dependecy might be a class, an instance or a lambda
4
+ # evaluate the lambda if necessary
5
+ def evaluate_dependency(dependency)
6
+ if dependency.is_a?(Proc)
7
+ return dependency.call
8
+ else
9
+ dependency
5
10
  end
11
+ end
6
12
 
7
- module ClassMethods
8
- def dependency(name, default_dep)
9
- define_method(name) do
10
- cached = instance_variable_get("@#{name}")
11
- return cached if cached
12
- instance_variable_set("@#{name}", default_dep)
13
- default_dep
14
- end
15
- define_method("#{name}=") do |injected|
16
- instance_variable_set("@#{name}", injected)
17
- end
18
- define_method("reset_#{name}") do
19
- instance_variable_set("@#{name}", default_dep)
20
- end
21
- end
13
+ def dependency(name, default_dep)
14
+
15
+ define_method(name) do
16
+ cached = instance_variable_get("@#{name}")
17
+ return cached if cached
18
+ self.send "reset_#{name}"
19
+ end
20
+
21
+ define_method("#{name}=") do |injected|
22
+ self.prepare_collaborator(name, injected) if self.respond_to?(:prepare_collaborator)
23
+ instance_variable_set("@#{name}", injected)
22
24
  end
23
25
 
26
+ define_method("reset_#{name}") do
27
+ evaluated = self.class.evaluate_dependency(default_dep)
28
+ self.prepare_collaborator(name, evaluated) if self.respond_to?(:prepare_collaborator)
29
+ instance_variable_set("@#{name}", evaluated)
30
+ evaluated
31
+ end
32
+
33
+ end
34
+
35
+
24
36
  end
data/readme.markdown CHANGED
@@ -1,7 +1,74 @@
1
1
  Collaborator
2
2
  ==========
3
3
 
4
- A simple gem for injecting dependencies into classes
4
+ A simple gem for injecting dependencies into classes. I got bored of copying the same code again and again so I made this simple gem.
5
+
6
+ Usage
7
+ -----
8
+
9
+ class BugFinder
10
+ ...
11
+ end
12
+
13
+ class BugKiller
14
+ # mixing the Collaborator module
15
+ extend Collaborator
16
+
17
+ # declare a dependency, pass an instance of the collaborator object
18
+ dependency :bug_finder, BugFinder.new
19
+ end
20
+
21
+ The dependecy method just creates a couple of attribute accesors, so you can use the dependecy like this:
22
+
23
+ class BugKiller
24
+ extend Collaborator
25
+ dependency :bug_finder, BugFinder.new
26
+
27
+ def run
28
+ bugs = bug_finder.run
29
+ ...
30
+ end
31
+
32
+ end
33
+
34
+ ### Injecting dependencies
35
+
36
+ In your test you just inject a new dependency like so:
37
+
38
+ bug_killer = BugKiller.new
39
+ bug_killer.bug_finder = mocked_bug_finder
40
+
41
+ ### Lazy evaluation
42
+
43
+ You can also pass a lambda as the second argument, this will defer evaluation of the dependecy until it is actually used
44
+
45
+ class BugKiller
46
+ extend Collaborator
47
+ dependency :bug_finder, ->{ BugFinder.new }
48
+
49
+ def run
50
+ bugs = bug_finder.run
51
+ ...
52
+ end
53
+
54
+ end
55
+
56
+ ### Preparing collaborators
57
+
58
+ Sometimes it is useful to prepare the collaborators in some way before actually using them. To do this just create a method in your class called 'prepare_collaborator'.
59
+
60
+ class BugKiller
61
+ extend Collaborator
62
+ dependency :bug_finder, ->{ BugFinder.new }
63
+
64
+ # this function receives the name of the collaborator e.g. :bug_finder and the collaborator itself
65
+ def prepare_collaborator(name, collaborator)
66
+ collaborator.log_enable = true
67
+ end
68
+
69
+ end
70
+
71
+ When a dependency is injected e.g. bug_killer.bug_finder = mocked_bug_finder this method is also called on the injected dependency
5
72
 
6
73
  Copyright
7
74
  ----------
@@ -1,17 +1,23 @@
1
1
  require 'spec_helper'
2
2
  require 'collaborator'
3
+ require 'ostruct'
3
4
 
4
5
  describe 'Collaborator' do
5
6
 
6
7
  let(:injected_collaborator) { double.as_null_object }
7
8
  let(:subject) { Subject.new }
8
9
 
9
- class Service
10
+ class Collaborator1
11
+ attr_accessor :foo
12
+ def run
13
+ true
14
+ end
10
15
  end
11
16
 
12
17
  class Subject
13
- include Collaborator
14
- dependency :collaborator, Service.new
18
+ extend Collaborator
19
+ dependency :collaborator1, Collaborator1.new
20
+ dependency :collaborator2, ->{ Collaborator1.new }
15
21
  end
16
22
 
17
23
  it "mixes in the module" do
@@ -19,30 +25,89 @@ describe 'Collaborator' do
19
25
  end
20
26
 
21
27
  it "creates a getter method" do
22
- expect(subject).to respond_to(:collaborator)
28
+ expect(subject).to respond_to(:collaborator1)
23
29
  end
24
30
 
25
31
  it "creates a setter method" do
26
- expect(subject).to respond_to(:collaborator=)
32
+ expect(subject).to respond_to(:collaborator1=)
27
33
  end
28
34
 
29
35
  it "creates a reset method" do
30
- expect(subject).to respond_to(:reset_collaborator)
36
+ expect(subject).to respond_to(:reset_collaborator1)
31
37
  end
32
38
 
33
- it "returns the default collaborator" do
34
- expect(subject.collaborator).to be_instance_of(Service)
39
+ it "reached the collaborator object" do
40
+ expect(subject.collaborator1.run).to be_true
41
+ end
42
+
43
+ it "returns the default collaborator1" do
44
+ expect(subject.collaborator1).to be_instance_of(Collaborator1)
35
45
  end
36
46
 
37
47
  it "can inject the dependency" do
38
- subject.collaborator = injected_collaborator
39
- expect(subject.collaborator).to eq(injected_collaborator)
48
+ subject.collaborator1 = injected_collaborator
49
+ expect(subject.collaborator1).to eq(injected_collaborator)
40
50
  end
41
51
 
42
52
  it "can reset the dependency" do
43
- subject.collaborator = injected_collaborator
44
- subject.reset_collaborator
45
- expect(subject.collaborator).to be_instance_of(Service)
53
+ subject.collaborator1 = injected_collaborator
54
+ subject.reset_collaborator1
55
+ expect(subject.collaborator1).to be_instance_of(Collaborator1)
46
56
  end
47
57
 
58
+ it "accepts a lambda" do
59
+ expect(subject).to respond_to(:collaborator2)
60
+ expect(subject.collaborator2.run).to be_true
61
+ end
62
+
63
+ describe "#prepare_collaborator" do
64
+
65
+ let(:subject2) { SubjectWithPrepareCollaborator.new }
66
+
67
+ class SubjectWithPrepareCollaborator
68
+ extend Collaborator
69
+ dependency :collaborator1, Collaborator1.new
70
+
71
+ def prepare_collaborator(name, collaborator)
72
+ collaborator.foo = 9
73
+ end
74
+ end
75
+
76
+ it 'gets call when using the dependency' do
77
+ subject2.should_receive(:prepare_collaborator)
78
+ subject2.collaborator1
79
+ end
80
+
81
+ it 'passes the name of the collaborator' do
82
+ subject2.stub(:prepare_collaborator) do |name, collaborator|
83
+ expect(name).to eq(:collaborator1)
84
+ end
85
+ subject2.collaborator1
86
+ end
87
+
88
+ it 'passes the reference to the collaborator' do
89
+ subject2.stub(:prepare_collaborator) do |name, collaborator|
90
+ expect(collaborator).to be_instance_of(Collaborator1)
91
+ end
92
+ subject2.collaborator1
93
+ end
94
+
95
+ it 'gets call when a dependency is injected' do
96
+ subject2.should_receive(:prepare_collaborator)
97
+ subject2.collaborator1 = injected_collaborator
98
+ end
99
+
100
+ it "runs the code in the method" do
101
+ expect(subject2.collaborator1.foo).to eq(9)
102
+ end
103
+
104
+ it "runs the code in the method for an injected collaborator" do
105
+ injected = OpenStruct.new
106
+ subject2.collaborator1 = injected
107
+ expect(injected.foo).to eq(9)
108
+ end
109
+
110
+ end
111
+
112
+
48
113
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: collaborator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -125,7 +125,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
125
125
  version: '0'
126
126
  segments:
127
127
  - 0
128
- hash: 3557498814883905141
128
+ hash: 2528418177998634082
129
129
  required_rubygems_version: !ruby/object:Gem::Requirement
130
130
  none: false
131
131
  requirements: