pharrell 0.8.0 → 0.8.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3c591314692d9690e8940b3f0b72b8dc1cc3926c
4
- data.tar.gz: e7e948670a4f517771e7bdcf4207579e1557706f
3
+ metadata.gz: 215dcc88ee3de7ae14a1eeddedc53c20107eff12
4
+ data.tar.gz: 3c764dea55c0a016897d48aebf45dcda94d36ab1
5
5
  SHA512:
6
- metadata.gz: e893aea8b98ef7bf417db1006d2879ff3d567fe9f4dd4ebbd0d9361cdf5a2663c9db3e976d1be745e8ca07a5552291d83fd51afc2f169f95732fbb453c85b390
7
- data.tar.gz: 658f2f56202b8e1a2b277ed37e075ee59763cd0d9d9456e47085b87c2d0dc7a41a5db24e054bedd6bca6fc895e243dae87d35d99bce83d4add5ef9baccb55840
6
+ metadata.gz: 5fdb941ba17003b0d38ece0bce1afeb6badef92813bda177b9488ecf4c3813c3a339e5217f8035560b20d3b0ae4c89fa39dff7fa1569acb3947fe69ba288c866
7
+ data.tar.gz: 9aa73f0950dfe32bccfb8879ef3a4ad2a88feaf388947f0e77103cbc6268aa50a9585f20de63510024690595e4000141bcf21348ab34af4de36257a8adbeeabf
data/.gitignore CHANGED
@@ -1 +0,0 @@
1
- coverage/*
data/.travis.yml CHANGED
@@ -2,4 +2,5 @@ language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
4
  - 2.0.0
5
+ - 2.1.0
5
6
  - jruby-19mode
data/Gemfile CHANGED
@@ -4,5 +4,4 @@ gemspec
4
4
 
5
5
  group :test do
6
6
  gem 'rake'
7
- gem 'coveralls'
8
7
  end
data/Gemfile.lock CHANGED
@@ -1,37 +1,16 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pharrell (0.8.0)
4
+ pharrell (0.8.1)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
- coveralls (0.7.0)
10
- multi_json (~> 1.3)
11
- rest-client
12
- simplecov (>= 0.7)
13
- term-ansicolor
14
- thor
15
- docile (1.1.3)
16
- mime-types (2.2)
17
- multi_json (1.9.2)
18
9
  rake (10.1.1)
19
- rest-client (1.6.7)
20
- mime-types (>= 1.16)
21
- simplecov (0.8.2)
22
- docile (~> 1.1.0)
23
- multi_json
24
- simplecov-html (~> 0.8.0)
25
- simplecov-html (0.8.0)
26
- term-ansicolor (1.3.0)
27
- tins (~> 1.0)
28
- thor (0.18.1)
29
- tins (1.0.1)
30
10
 
31
11
  PLATFORMS
32
12
  ruby
33
13
 
34
14
  DEPENDENCIES
35
- coveralls
36
15
  pharrell!
37
16
  rake
data/README.md CHANGED
@@ -25,7 +25,7 @@ You can inject dependencies into classes like so:
25
25
 
26
26
  ```ruby
27
27
  class BlackBox
28
- include Pharrell::Injectible
28
+ include Pharrell::Injectable
29
29
 
30
30
  injected :current_time, Time
31
31
 
@@ -36,7 +36,7 @@ class BlackBox
36
36
  end
37
37
  ```
38
38
 
39
- The values injected are dependent on the current conifguration:
39
+ The values injected are dependent on the current configuration:
40
40
 
41
41
  ```ruby
42
42
  Pharrell.config(:base) do |config|
@@ -47,7 +47,7 @@ Pharrell.use_config(:base)
47
47
  ```
48
48
 
49
49
  You can use configurations to change the injected values in different
50
- scenarios. For instance, we can use Pharrell to help us test `CurrentTime` class
50
+ scenarios. For instance, we can use Pharrell to help us test the `BlackBox` class
51
51
  defined above:
52
52
 
53
53
  ```ruby
@@ -71,12 +71,12 @@ end
71
71
  ### Constructor Injection
72
72
 
73
73
  When you're working with objects that have to be a black box
74
- (like a Rails controller for instance) you will need to inject dependencies
74
+ (like a Rails controller for instance) you will need to inject dependencies artificially
75
75
  like in the basic example before. It's a lot nicer to be able to design your
76
76
  other objects so their dependencies are injected directly into their constructor i.e.
77
- they do not cheat. This will make your components easier reason about and easier to test.
77
+ they do not cheat. This will make your components easier to reason about and easier to test.
78
78
 
79
- We can break the previous time code into into its object to achieve this:
79
+ We can break the previous example into its object to achieve this:
80
80
 
81
81
  ```ruby
82
82
  class PrettyTime
@@ -91,8 +91,8 @@ class PrettyTime
91
91
  end
92
92
  ```
93
93
 
94
- This is great but what if we want to construct `PrettyTime` of these in the
95
- `BlackBox` class?
94
+ This is great but what if we want to construct a `PrettyTime` instance in the
95
+ `BlackBox` class without having to inject `Time`?
96
96
 
97
97
  For this we can use constructor injection:
98
98
 
@@ -117,7 +117,7 @@ We can then inject `PrettyTime` straight into `BlackBox`:
117
117
 
118
118
  ```ruby
119
119
  class BlackBox
120
- include Pharrell::Injectible
120
+ include Pharrell::Injectable
121
121
 
122
122
  injected :pretty_time, PrettyTime
123
123
 
@@ -145,8 +145,8 @@ magic dependency injection (DI frameworks, stubbing factories etc) anywhere but
145
145
 
146
146
  ### Bindings
147
147
 
148
- When building configurations in pharrell you can bind instances to
149
- produce to classes in three different ways:
148
+ When building configurations in pharrell you can bind instances in three different
149
+ ways:
150
150
 
151
151
  ```ruby
152
152
  Pharrell.config(:example) do |config|
@@ -219,3 +219,11 @@ end
219
219
 
220
220
  Pharrell should be configured in the Rails Application's `#to_prepare` method as this runs at startup
221
221
  in production and before each request in development.
222
+
223
+ ## Contributing
224
+
225
+ 1. Fork it
226
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
227
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
228
+ 4. Push to the branch (`git push origin my-new-feature`)
229
+ 5. Create new Pull Request
data/lib/pharrell.rb CHANGED
@@ -4,60 +4,90 @@ require 'pharrell/constructor'
4
4
  require 'pharrell/errors'
5
5
 
6
6
  module Pharrell
7
- @@configs = {}
8
- @@config = nil
7
+ @@environment = nil
9
8
 
10
9
  def self.config(name, opts = {}, &blk)
11
- check_options([:extends], opts)
12
-
13
- if opts[:extends]
14
- @@configs[name] = fetch_config(opts[:extends]).extend(blk)
15
- else
16
- @@configs[name] = Config.new(blk)
17
- end
10
+ environment.config(name, opts, &blk)
18
11
  end
19
12
 
20
13
  def self.use_config(name)
21
- @@config = name
22
- rebuild!
14
+ environment.use_config(name)
23
15
  end
24
16
 
25
17
  def self.instance_for(klass)
26
- current_config.instance_for(klass)
18
+ environment.instance_for(klass)
27
19
  end
28
20
 
29
21
  def self.rebuild!
30
- current_config.rebuild!
22
+ environment.rebuild!
31
23
  end
32
24
 
33
25
  def self.reset!
34
- @@configs = {}
35
- @@config = nil
26
+ environment.reset!
36
27
  end
37
28
 
38
29
  private
39
30
 
40
- def self.current_config
41
- fetch_config(@@config)
31
+ def self.environment
32
+ @@enironment ||= Environment.new
42
33
  end
43
34
 
44
- def self.fetch_config(name)
45
- config = @@configs[name]
35
+ class Environment
36
+ @configs = {}
37
+ @config = nil
38
+
39
+ def config(name, opts = {}, &blk)
40
+ check_options([:extends], opts)
46
41
 
47
- if config
48
- config
49
- else
50
- raise ConfigNotDefinedError
42
+ if opts[:extends]
43
+ @configs[name] = fetch_config(opts[:extends]).extend(blk)
44
+ else
45
+ @configs[name] = Config.new(blk)
46
+ end
47
+ end
48
+
49
+ def use_config(name)
50
+ @config = name
51
+ rebuild!
52
+ end
53
+
54
+ def instance_for(klass)
55
+ current_config.instance_for(klass)
56
+ end
57
+
58
+ def rebuild!
59
+ current_config.rebuild!
60
+ end
61
+
62
+ def reset!
63
+ @configs = {}
64
+ @config = nil
65
+ end
66
+
67
+ private
68
+
69
+ def current_config
70
+ fetch_config(@config)
71
+ end
72
+
73
+ def fetch_config(name)
74
+ config = @configs[name]
75
+
76
+ if config
77
+ config
78
+ else
79
+ raise ConfigNotDefinedError.new(name)
80
+ end
51
81
  end
52
- end
53
82
 
54
- def self.check_options(opts, opt_hash)
55
- extra_keys = opt_hash.keys.reject { |key| opts.include?(key) }
83
+ def check_options(opts, opt_hash)
84
+ extra_keys = opt_hash.keys.reject { |key| opts.include?(key) }
56
85
 
57
- if extra_keys.empty?
58
- true
59
- else
60
- raise InvalidOptionsError.new(extra_keys)
86
+ if extra_keys.empty?
87
+ true
88
+ else
89
+ raise InvalidOptionsError.new(extra_keys)
90
+ end
61
91
  end
62
92
  end
63
93
  end
@@ -6,26 +6,26 @@ module Pharrell
6
6
 
7
7
  def instance_for(klass)
8
8
  binding = @bindings[klass]
9
-
9
+
10
10
  if binding
11
11
  binding.call(self)
12
12
  else
13
- raise BindingNotFoundError
13
+ raise BindingNotFoundError.new(klass)
14
14
  end
15
15
  end
16
16
 
17
17
  def rebuild!
18
- @bindings = Binder.new.tap { |b|
18
+ @bindings = Binder.new.tap { |b|
19
19
  @definition.call(b)
20
20
  }.bindings
21
21
  end
22
22
 
23
23
  def extend(definition)
24
- agg_definition = proc { |binder|
24
+ agg_definition = proc { |binder|
25
25
  @definition.call(binder)
26
- definition.call(binder)
26
+ definition.call(binder)
27
27
  }
28
-
28
+
29
29
  Config.new(agg_definition)
30
30
  end
31
31
 
@@ -51,15 +51,15 @@ module Pharrell
51
51
  @bindings[klass] = obj_block
52
52
  end
53
53
  end
54
-
54
+
55
55
  private
56
-
56
+
57
57
  def build_instance(target_klass, config)
58
58
  if target_klass.respond_to?(:__pharrell_constructor_classes)
59
59
  args = target_klass.__pharrell_constructor_classes.map do |arg_klass|
60
60
  config.instance_for(arg_klass)
61
61
  end
62
-
62
+
63
63
  target_klass.new(*args)
64
64
  else
65
65
  target_klass.new
@@ -68,4 +68,3 @@ module Pharrell
68
68
  end
69
69
  end
70
70
  end
71
-
@@ -1,13 +1,21 @@
1
1
  module Pharrell
2
2
  class BindingNotFoundError < Exception
3
+ def initialize(klass)
4
+ @klass = klass
5
+ end
6
+
3
7
  def message
4
- "Binding could not be found!"
8
+ "Binding for #{@klass} could not be found!"
5
9
  end
6
10
  end
7
11
 
8
12
  class ConfigNotDefinedError < Exception
13
+ def initialize(config)
14
+ @config = config
15
+ end
16
+
9
17
  def message
10
- "Config has not been defined!"
18
+ "Config '#{@config}' has not been defined!"
11
19
  end
12
20
  end
13
21
 
@@ -5,6 +5,8 @@ module Pharrell
5
5
  end
6
6
 
7
7
  module ClassMethods
8
+ @@cache = {}
9
+
8
10
  def injected(name, klass=nil)
9
11
  if klass.nil?
10
12
  klass_name = name.to_s.split("_").map(&:capitalize).join
@@ -12,8 +14,8 @@ module Pharrell
12
14
  end
13
15
 
14
16
  define_method(name) do
15
- @__pharrell_cache__ ||= {}
16
- @__pharrell_cache__[klass] ||= Pharrell.instance_for(klass)
17
+ @@cache[self] ||= {}
18
+ @@cache[self][klass] ||= Pharrell.instance_for(klass)
17
19
  end
18
20
  end
19
21
  end
@@ -0,0 +1,26 @@
1
+ module Pharrell
2
+ module Integration
3
+ module RSpec
4
+ def self.configure(config_name, rspec_config)
5
+ rspec_config.include(Pharrell::Injectable)
6
+ rspec_config.include(Pharrell::Integration::RSpec)
7
+
8
+ rspec_config.before(:each) do
9
+ Pharrell.use_config(config_name)
10
+ end
11
+ end
12
+
13
+ def self.included(base)
14
+ base.extend(ClassMethods)
15
+ end
16
+
17
+ module ClassMethods
18
+ def use_config(config)
19
+ before(:each) do
20
+ Pharrell.use_config(config)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
data/pharrell.gemspec CHANGED
@@ -3,11 +3,12 @@ $:.unshift lib unless $:.include?(lib)
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "pharrell"
6
- s.version = "0.8.0"
6
+ s.version = "0.8.1"
7
7
  s.platform = Gem::Platform::RUBY
8
8
  s.authors = ["Callum Stott"]
9
9
  s.email = ["callum@seadowg.com"]
10
10
  s.summary = "I'm a provider gurl. Basic but powerful dependency injection for Ruby."
11
+ s.description = "A dependency injection framework for Ruby. Allows Guice like functionality with both field and constructor injection."
11
12
  s.license = 'MIT'
12
13
  s.homepage = "http://github.com/seadowg/pharrell"
13
14
 
@@ -57,6 +57,7 @@ describe "Injectable" do
57
57
 
58
58
  object = klass.new
59
59
  assert_equal(object.send(:injected_ob), object.send(:injected_ob))
60
+ refute_equal(object.send(:injected_ob), klass.new.send(:injected_ob))
60
61
  end
61
62
  end
62
63
  end
@@ -0,0 +1,67 @@
1
+ require 'spec_helper'
2
+ require 'minitest/autorun'
3
+ require 'pharrell'
4
+ require 'pharrell/integration/rspec'
5
+
6
+ describe "Integration" do
7
+ before do
8
+ Pharrell.reset!
9
+ FakeRSpec.reset!
10
+ end
11
+
12
+ describe "RSpec" do
13
+ describe ".use_config" do
14
+ it "sets the Pharrell config using before each" do
15
+ fake_spec = Class.new(FakeRSpec) do
16
+ include Pharrell::Integration::RSpec
17
+ use_config(:test)
18
+ end
19
+
20
+ Pharrell.config(:base) do |config|
21
+ config.bind(String, "Base")
22
+ end
23
+
24
+ Pharrell.config(:test) do |config|
25
+ config.bind(String, "Test")
26
+ end
27
+
28
+ Pharrell.use_config(:base)
29
+
30
+ fake_spec.new
31
+ befores = fake_spec.befores
32
+
33
+ assert_equal(1, befores[:each].length)
34
+ assert_equal("Base", Pharrell.instance_for(String))
35
+
36
+ befores[:each].first.call
37
+ assert_equal("Test", Pharrell.instance_for(String))
38
+ end
39
+ end
40
+
41
+ describe ".configure" do
42
+ it "sets up RSpec for use with Pharrell with theh passed config" do
43
+ fake_rspec = Class.new(FakeRSpec)
44
+ Pharrell::Integration::RSpec.configure(:test, fake_rspec)
45
+
46
+ Pharrell.config(:base) do |config|
47
+ config.bind(String, "Base")
48
+ end
49
+
50
+ Pharrell.config(:test) do |config|
51
+ config.bind(String, "Test")
52
+ end
53
+
54
+ Pharrell.use_config(:base)
55
+
56
+ fake_rspec.new
57
+ befores = fake_rspec.befores
58
+
59
+ assert_equal(1, befores[:each].length)
60
+ assert_equal("Base", Pharrell.instance_for(String))
61
+
62
+ befores[:each].first.call
63
+ assert_equal("Test", Pharrell.instance_for(String))
64
+ end
65
+ end
66
+ end
67
+ end
@@ -6,7 +6,7 @@ describe "Pharrell" do
6
6
  before do
7
7
  Pharrell.reset!
8
8
  end
9
-
9
+
10
10
  describe ".use_config" do
11
11
  it "switches Pharrell to use the specified config" do
12
12
  Pharrell.config(:test) do |config|
@@ -37,13 +37,13 @@ describe "Pharrell" do
37
37
 
38
38
  assert(first_instance != second_instance)
39
39
  end
40
-
40
+
41
41
  it "raises a ConfigNotDefinedError if the config does not exist" do
42
42
  begin
43
43
  Pharrell.use_config(:main)
44
44
  flunk(".use_config did not raise an error!")
45
45
  rescue Pharrell::ConfigNotDefinedError => e
46
- assert_equal("Config has not been defined!", e.message)
46
+ assert_equal("Config 'main' has not been defined!", e.message)
47
47
  end
48
48
  end
49
49
  end
@@ -63,16 +63,16 @@ describe "Pharrell" do
63
63
  assert_equal(Pharrell.instance_for(Object), "Object")
64
64
  assert_equal(Pharrell.instance_for(String), "Hello, Test")
65
65
  end
66
-
66
+
67
67
  it "raises a ConfigNotDefinedError if the extended config does not exist" do
68
68
  begin
69
69
  Pharrell.config(:sub, :extends => :base)
70
70
  flunk(".config did not raise an error!")
71
71
  rescue Pharrell::ConfigNotDefinedError => e
72
- assert_equal("Config has not been defined!", e.message)
72
+ assert_equal("Config 'base' has not been defined!", e.message)
73
73
  end
74
74
  end
75
-
75
+
76
76
  it "raises an InvalidOptionsError for invalid options" do
77
77
  begin
78
78
  Pharrell.config(:base, :wrong_opt => "Value", :other_opt => "Value") { |config| }
@@ -96,18 +96,18 @@ describe "Pharrell" do
96
96
  assert(Pharrell.instance_for(Object) != original)
97
97
  end
98
98
  end
99
-
99
+
100
100
  describe ".instance_for" do
101
101
  it "raises a BindingNotFoundError if there is no binding for the instance" do
102
102
  Pharrell.config(:main) { |config| }
103
103
  Pharrell.use_config(:main)
104
-
104
+
105
105
  begin
106
106
  Pharrell.instance_for(Object)
107
107
  flunk(".instance_for did not raise an error!")
108
108
  rescue Pharrell::BindingNotFoundError => e
109
- assert_equal("Binding could not be found!", e.message)
110
- end
109
+ assert_equal("Binding for Object could not be found!", e.message)
110
+ end
111
111
  end
112
112
  end
113
113
  end
data/spec/spec_helper.rb CHANGED
@@ -1,9 +1 @@
1
- require 'simplecov'
2
- SimpleCov.start do
3
- add_filter do |source_file|
4
- source_file.filename =~ /spec/
5
- end
6
- end
7
-
8
- require 'coveralls'
9
- Coveralls.wear!
1
+ require_relative "support/fake_rspec"
@@ -0,0 +1,19 @@
1
+ class FakeRSpec
2
+ @@befores = Hash.new([])
3
+
4
+ def self.before(scope, &blk)
5
+ @@befores[scope] << blk
6
+ end
7
+
8
+ def self.befores
9
+ @@befores
10
+ end
11
+
12
+ def self.include(modjewel)
13
+ super(modjewel)
14
+ end
15
+
16
+ def self.reset!
17
+ @@befores = Hash.new([])
18
+ end
19
+ end
metadata CHANGED
@@ -1,16 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pharrell
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Callum Stott
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-21 00:00:00.000000000 Z
11
+ date: 2014-04-29 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description:
13
+ description: A dependency injection framework for Ruby. Allows Guice like functionality
14
+ with both field and constructor injection.
14
15
  email:
15
16
  - callum@seadowg.com
16
17
  executables: []
@@ -29,13 +30,16 @@ files:
29
30
  - lib/pharrell/constructor.rb
30
31
  - lib/pharrell/errors.rb
31
32
  - lib/pharrell/injectable.rb
33
+ - lib/pharrell/integration/rspec.rb
32
34
  - media/pharrell.jpg
33
35
  - pharrell.gemspec
34
36
  - spec/config_spec.rb
35
37
  - spec/constructor_spec.rb
36
38
  - spec/injectable_spec.rb
39
+ - spec/integration_spec.rb
37
40
  - spec/pharrell_spec.rb
38
41
  - spec/spec_helper.rb
42
+ - spec/support/fake_rspec.rb
39
43
  homepage: http://github.com/seadowg/pharrell
40
44
  licenses:
41
45
  - MIT