collaborator 0.0.1 → 0.0.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/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: