payload 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6fa079c6398f542f86d57e0d7877adfd70566478
4
- data.tar.gz: e2ac201ce98bd76fcc49bc8356d326a4a72e16db
3
+ metadata.gz: b10fd4f4978e6e012a6a0de2afb3ddd2d0a42213
4
+ data.tar.gz: 4f8f29b9e509d9187d7069af752af5bbb4ebd3ab
5
5
  SHA512:
6
- metadata.gz: 44d7f4b24a8cfa7aa9b81dfdce4e1c428727352ecffd8c21010c980723022cbe6b94519d5525082a45903556fc8241c1a032cb5c57eee4fa5f37e81c13ea31f4
7
- data.tar.gz: bc383b6d05c0bc47a49c1cc56159437db0a1937484fbfb724d75557316bf8b996707a2ef0f8475d36e15b7038a80ccc3d4e9a507a59182e569bb4acab9611263
6
+ metadata.gz: bf4b151ea4ce615e0eac8a522768d8e4e4b63b8b47ed9cb392a7b053a9fadecfe5cc2a6b68da3e3375a8ab305e34732f553b85e85ce55c78fa5ddef03add86fc
7
+ data.tar.gz: 906535970e22a92f507b48e14a37a2b2ec16ce6ba23fa63f9591bda7a909d73c0acb649e21d684891db10ea8eb1e2a562b7f376143e340cdf4b23276ce64db0f
data/.gitignore CHANGED
@@ -1,4 +1,5 @@
1
1
  .bundle
2
2
  .yardoc
3
+ coverage
3
4
  doc
4
5
  pkg
@@ -0,0 +1,7 @@
1
+ addons:
2
+ code_climate:
3
+ repo_token: adbc28d8c3bd765fc6aa418515aa036b275608c9d42a2326d3133b1231f14741
4
+
5
+ rvm:
6
+ - 2.0.0
7
+ - 2.1.0
@@ -1,12 +1,16 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- payload (0.2.2)
4
+ payload (0.3.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
+ codeclimate-test-reporter (0.2.0)
10
+ simplecov (>= 0.7.1, < 1.0.0)
9
11
  diff-lcs (1.2.5)
12
+ docile (1.1.5)
13
+ multi_json (1.10.1)
10
14
  rack (1.5.2)
11
15
  rake (10.3.2)
12
16
  rspec (3.1.0)
@@ -21,11 +25,17 @@ GEM
21
25
  rspec-mocks (3.1.3)
22
26
  rspec-support (~> 3.1.0)
23
27
  rspec-support (3.1.2)
28
+ simplecov (0.9.1)
29
+ docile (~> 1.1.0)
30
+ multi_json (~> 1.0)
31
+ simplecov-html (~> 0.8.0)
32
+ simplecov-html (0.8.0)
24
33
 
25
34
  PLATFORMS
26
35
  ruby
27
36
 
28
37
  DEPENDENCIES
38
+ codeclimate-test-reporter
29
39
  payload!
30
40
  rack
31
41
  rake
data/README.md CHANGED
@@ -71,8 +71,8 @@ from controllers entirely.
71
71
  In `config/dependencies.rb`:
72
72
 
73
73
  ```ruby
74
- factory :payment do |container|
75
- Payment.new(container[:attributes], container[:payment_client])
74
+ factory :payment do |container, attributes|
75
+ Payment.new(attributes, container[:payment_client])
76
76
  end
77
77
  ```
78
78
 
@@ -81,7 +81,7 @@ In `app/controllers/payments_controller.rb`:
81
81
  ```ruby
82
82
  class PaymentsController < ApplicationController
83
83
  def create
84
- payment = dependencies[:payment].new(attributes: params[:payment])
84
+ payment = dependencies[:payment].new(params[:payment])
85
85
  payment.process
86
86
  redirect_to payment
87
87
  end
@@ -95,7 +95,7 @@ describe PaymentsController do
95
95
  describe '#create' do
96
96
  it 'processes a payment' do
97
97
  payment_params = { product_id: '123', amount: '25' }
98
- payment = stub_factory_instance(:payment, attributes: payment_params)
98
+ payment = stub_factory_instance(:payment, payment_params)
99
99
 
100
100
  post :create, payment_params
101
101
 
@@ -151,13 +151,13 @@ Use the `factory` method to define dependencies which require dependencies from
151
151
  the container as well as runtime state which varies per-request:
152
152
 
153
153
  ```ruby
154
- factory :payment do |container|
155
- Payment.new(container[:attributes], container[:payment_client])
154
+ factory :payment do |container, attributes|
155
+ Payment.new(attributes, container[:payment_client])
156
156
  end
157
157
  ```
158
158
 
159
- The container for factory definitions contains all dependencies defined on the
160
- container as well as dependencies provided when instantiating the factory.
159
+ Any additional arguments passed to `new` when instantiating the factory will
160
+ also be passed to the factory definition block.
161
161
 
162
162
  Use the `decorate` method to extend or replace a previously defined dependency:
163
163
 
@@ -193,15 +193,15 @@ Use `new` to instantiate dependencies from factories:
193
193
  ```ruby
194
194
  class PaymentsController < ApplicationController
195
195
  def create
196
- payment = dependencies[:payment].new(attributes: params[:payment])
196
+ payment = dependencies[:payment].new(params[:payment])
197
197
  payment.process
198
198
  redirect_to payment
199
199
  end
200
200
  end
201
201
  ```
202
202
 
203
- The `new` method accepts a `Hash`. Each element of the `Hash` will be accessible
204
- from the container in `factory` definitions.
203
+ All arguments to the `new` method will be passed to the factory definition
204
+ block.
205
205
 
206
206
  Grouping Dependencies
207
207
  ---------------------
@@ -222,8 +222,8 @@ service :payment_notifier do |container|
222
222
  PaymentNotifier.new(container[:mailer])
223
223
  end
224
224
 
225
- factory :payment do |container|
226
- Payment.new(container[:attributes], container[:payment_client])
225
+ factory :payment do |container, attributes|
226
+ Payment.new(attributes, container[:payment_client])
227
227
  end
228
228
 
229
229
  decorate :payment do |payment, container|
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rake' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('rake', 'rake')
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # This file was generated by Bundler.
4
+ #
5
+ # The application 'rspec' is installed as part of a gem, and
6
+ # this file is here to facilitate running it.
7
+ #
8
+
9
+ require 'pathname'
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path("../../Gemfile",
11
+ Pathname.new(__FILE__).realpath)
12
+
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
+
16
+ load Gem.bin_path('rspec-core', 'rspec')
@@ -16,9 +16,9 @@ module Payload
16
16
  self.class.new decorators + [decorator]
17
17
  end
18
18
 
19
- def decorate(base, container)
19
+ def decorate(base, container, *extra)
20
20
  decorators.inject(base) do |component, decorator|
21
- decorator.call(component, container)
21
+ decorator.call(component, container, *extra)
22
22
  end
23
23
  end
24
24
 
@@ -5,7 +5,7 @@ module Payload
5
5
  # Definition for a dependency which can be resolved and decorated.
6
6
  #
7
7
  # Used internally by {DefinitionList}. Use {Container#service} or
8
- # {Container#fatory}.
8
+ # {Container#factory}.
9
9
  #
10
10
  # @api private
11
11
  class Definition
@@ -1,3 +1,5 @@
1
+ require "payload/partial_instance"
2
+
1
3
  module Payload
2
4
  # Returned by {Container#[]} for {Container#factory} definitions.
3
5
  #
@@ -15,19 +17,34 @@ module Payload
15
17
  @decorators = decorators
16
18
  end
17
19
 
18
- # @param [Hash] arguments additional dependencies and arguments to resolve
19
- # before invoking the factory definition block.
20
+ # @param [Array] arguments additional arguments to pass to the factory
21
+ # definition block.
20
22
  # @return the instance defined by the factory definition block.
21
23
  # @see Container#factory Container#factory for defining and using factories.
22
- def new(arguments = {})
23
- resolved =
24
- arguments.inject(@container) do |container, (argument, value)|
25
- container.service(argument) { value }
26
- end
27
-
28
- base = @block.call(resolved)
24
+ def new(*arguments)
25
+ base = @block.call(@container, *arguments)
26
+ @decorators.decorate(base, @container, *arguments)
27
+ end
29
28
 
30
- @decorators.decorate(base, resolved)
29
+ # Return a new factory with some of the arguments provided. Remaining
30
+ # arguments can be provided by invoking {Factory#new} on the returned
31
+ # instance. Chaining {Factory#apply} is also possible. This can be useful
32
+ # for returning a factory where some of the dependencies are provided by the
33
+ # container, and the remainder are provided at runtime.
34
+ #
35
+ # @example
36
+ # container = Payload::Container.new.
37
+ # factory(:form) { |container, model, attributes|
38
+ # Form.new(model, attributes)
39
+ # }.
40
+ # service(:user_form) { |container| container[:form].apply(User) }
41
+ # user_form = container[:user_form].new(username: "smith")
42
+ # @param [Array] arguments positional arguments to be passed to the factory
43
+ # @param [Hash] keywords keyword arguments to be passed to the factory
44
+ # @return [PartialInstance] an instance on which you can invoke
45
+ # {Factory#new}.
46
+ def apply(*arguments, **keywords)
47
+ PartialInstance.new(self).apply(*arguments, **keywords)
31
48
  end
32
49
  end
33
50
  end
@@ -0,0 +1,57 @@
1
+ module Payload
2
+ # Returned by {Factory#apply}.
3
+ #
4
+ # Used to build up arguments for invoking factory definitions.
5
+ #
6
+ # @see Factory#apply Factory#apply for usage.
7
+ class PartialInstance
8
+ # Used internally by {Factory}.
9
+ #
10
+ # @api private
11
+ def initialize(instance, positional = [], keywords = {})
12
+ @instance = instance
13
+ @positional = positional
14
+ @keywords = keywords
15
+ end
16
+
17
+ # @see Factory#apply Factory#apply for usage.
18
+ def apply(*positional, **keywords)
19
+ self.class.new(
20
+ @instance,
21
+ @positional + positional,
22
+ @keywords.merge(keywords)
23
+ )
24
+ end
25
+
26
+ # Applies final arguments and invokes the missing method on the target.
27
+ #
28
+ # @see Factory#new Factory#new for usage.
29
+ def method_missing(name, *positional, **keywords, &block)
30
+ apply(*positional, **keywords).evaluate(name, &block)
31
+ end
32
+
33
+ protected
34
+
35
+ def evaluate(name, &block)
36
+ @instance.public_send(name, *arguments, &block)
37
+ end
38
+
39
+ private
40
+
41
+ def arguments
42
+ @positional + keyword_arguments
43
+ end
44
+
45
+ def keyword_arguments
46
+ if @keywords.empty?
47
+ []
48
+ else
49
+ [@keywords]
50
+ end
51
+ end
52
+
53
+ def respond_to_missing?(*arguments)
54
+ @instance.respond_to?(*arguments)
55
+ end
56
+ end
57
+ end
@@ -1,3 +1,3 @@
1
1
  module Payload
2
- VERSION = '0.2.2'
2
+ VERSION = "0.3.0"
3
3
  end
@@ -21,4 +21,5 @@ Gem::Specification.new do |s|
21
21
  s.add_development_dependency 'rack'
22
22
  s.add_development_dependency 'rake'
23
23
  s.add_development_dependency 'rspec', '~> 3.1.0'
24
+ s.add_development_dependency 'codeclimate-test-reporter'
24
25
  end
@@ -5,17 +5,17 @@ require 'payload/testing'
5
5
  describe Payload::Container do
6
6
  include Payload::Testing
7
7
 
8
- describe '#factory' do
9
- it 'returns an object that responds to new' do
10
- container = build_container
11
- .service(:from_container) { |config| 'From container' }
12
- .factory(:example) do |config|
13
- "#{config[:from_new]} and #{config[:from_container]}"
8
+ describe "#factory" do
9
+ it "returns an object that responds to new" do
10
+ container = build_container.
11
+ service(:from_container) { |config| "From container" }.
12
+ factory(:example) do |config, from_new|
13
+ "#{from_new} and #{config[:from_container]}"
14
14
  end
15
15
 
16
- result = container[:example].new(from_new: 'From new')
16
+ result = container[:example].new("From new")
17
17
 
18
- expect(result).to eq('From new and From container')
18
+ expect(result).to eq("From new and From container")
19
19
  end
20
20
  end
21
21
 
@@ -6,28 +6,42 @@ describe Payload::DecoratorChain do
6
6
  expect(Payload::DecoratorChain.new).to be_a(Enumerable)
7
7
  end
8
8
 
9
- describe '#decorate' do
10
- it 'applies a series of decorators to a component' do
11
- chain = Payload::DecoratorChain
12
- .new
13
- .add(lambda { |base, config| "Decorated #{base} with #{config[:one]}" })
14
- .add(lambda { |base, config| "#{base} and #{config[:two]}" })
9
+ describe "#decorate" do
10
+ it "applies a series of decorators to a component" do
11
+ chain = Payload::DecoratorChain.
12
+ new.
13
+ add(lambda { |base, config| "Decorated #{base} with #{config[:one]}" }).
14
+ add(lambda { |base, config| "#{base} and #{config[:two]}" })
15
15
 
16
- result = chain.decorate('original', one: 'one', two: 'two')
16
+ result = chain.decorate("original", one: "one", two: "two")
17
17
 
18
- expect(result).to eq('Decorated original with one and two')
18
+ expect(result).to eq("Decorated original with one and two")
19
+ end
20
+
21
+ it "applies a decorator with extra arguments" do
22
+ block = lambda do |base, config, extra|
23
+ "Decorated #{base} with #{config[:one]} and #{extra}"
24
+ end
25
+
26
+ chain = Payload::DecoratorChain.
27
+ new.
28
+ add(block)
29
+
30
+ result = chain.decorate("original", { one: "one", two: "two" }, "extra")
31
+
32
+ expect(result).to eq("Decorated original with one and extra")
19
33
  end
20
34
 
21
35
  it "doesn't mutate" do
22
- chain = Payload::DecoratorChain
23
- .new
24
- .add(lambda { |base, config| "Decorated #{base}" })
36
+ chain = Payload::DecoratorChain.
37
+ new.
38
+ add(lambda { |base, config| "Decorated #{base}" })
25
39
 
26
- chain.add(lambda { |base, config| 'Unreferenced decorator' })
40
+ chain.add(lambda { |base, config| "Unreferenced decorator" })
27
41
 
28
- result = chain.decorate('original', {})
42
+ result = chain.decorate("original", {})
29
43
 
30
- expect(result).to eq('Decorated original')
44
+ expect(result).to eq("Decorated original")
31
45
  end
32
46
  end
33
47
 
@@ -1,46 +1,56 @@
1
- require 'spec_helper'
2
- require 'payload/factory'
3
- require 'payload/decorator_chain'
4
- require 'payload/testing'
1
+ require "spec_helper"
2
+ require "payload/factory"
3
+ require "payload/decorator_chain"
4
+ require "payload/testing"
5
5
 
6
6
  describe Payload::Factory do
7
7
  include Payload::Testing
8
8
 
9
- describe '#new' do
10
- it 'instantiates the dependency' do
11
- decorator = lambda do |component, config|
12
- "Decorated #{component.inspect} " \
13
- "with #{config[:from_container]} " \
14
- "and #{config[:from_new]}"
9
+ describe "#new" do
10
+ it "instantiates the dependency" do
11
+ decorator = lambda do |component, config, from_new|
12
+ "Decorated #{component.inspect}" \
13
+ " with #{config[:from_container]} and #{from_new}"
15
14
  end
16
- block = lambda do |config|
17
- "Component with #{config[:from_container]} and #{config[:from_new]}"
15
+ block = lambda do |config, from_new|
16
+ "Component with #{config[:from_container]} and #{from_new}"
18
17
  end
19
18
  decorators = Payload::DecoratorChain.new.add(decorator)
20
- container = build_container
21
- .service(:from_container) { 'From container' }
19
+ container = build_container.service(:from_container) { "From container" }
22
20
  factory = Payload::Factory.new(container, block, decorators)
23
21
 
24
- result = factory.new(from_new: 'From new')
22
+ result = factory.new("From new")
25
23
 
26
24
  expect(result).to eq(
27
25
  'Decorated "Component with From container and From new" ' \
28
- 'with From container and From new'
26
+ "with From container and From new"
29
27
  )
30
28
  end
31
29
 
32
- it 'instantiates the dependency without arguments' do
30
+ it "instantiates the dependency without arguments" do
33
31
  block = lambda do |config|
34
32
  "Component with #{config[:from_container]}"
35
33
  end
36
34
  decorators = Payload::DecoratorChain.new
37
- container = build_container
38
- .service(:from_container) { 'From container' }
35
+ container = build_container.service(:from_container) { "From container" }
39
36
  factory = Payload::Factory.new(container, block, decorators)
40
37
 
41
38
  result = factory.new
42
39
 
43
- expect(result).to eq('Component with From container')
40
+ expect(result).to eq("Component with From container")
41
+ end
42
+ end
43
+
44
+ describe "#apply" do
45
+ it "applies arguments" do
46
+ container = build_container
47
+ block = lambda { |config, applied, local| "Got #{applied} and #{local}" }
48
+ decorators = Payload::DecoratorChain.new
49
+ factory = Payload::Factory.new(container, block, decorators)
50
+
51
+ result = factory.apply("applied").new("local")
52
+
53
+ expect(result).to eq("Got applied and local")
44
54
  end
45
55
  end
46
56
  end
@@ -0,0 +1,57 @@
1
+ require "spec_helper"
2
+ require "payload/partial_instance"
3
+
4
+ describe Payload::PartialInstance do
5
+ describe "#method_missing" do
6
+ context "for a method with only positional arguments" do
7
+ it "applies parameters from #initialize and #apply" do
8
+ block = lambda do |first, second, third|
9
+ [first, second, third]
10
+ end
11
+
12
+ result = Payload::PartialInstance.
13
+ new(block, ["first"], {}).
14
+ apply("second").
15
+ call("third")
16
+
17
+ expect(result).to eq(%w(first second third))
18
+ end
19
+ end
20
+
21
+ context "for a method with keyword arguments" do
22
+ it "combines keyword arguments" do
23
+ block = lambda do |first, second, third, a: nil, b: nil, c: nil|
24
+ [first, second, third, a, b, c]
25
+ end
26
+
27
+ result = Payload::PartialInstance.
28
+ new(block, ["first"], { a: "a" }).
29
+ apply("second", b: "b").
30
+ call("third", c: "c")
31
+
32
+ expect(result).to eq(%w(first second third a b c))
33
+ end
34
+ end
35
+ end
36
+
37
+ describe "#respond_to_missing?" do
38
+ context "for a method defined on its instance" do
39
+ it "returns true" do
40
+ instance = double("instance")
41
+ allow(instance).to receive(:example)
42
+ partial = Payload::PartialInstance.new(instance)
43
+
44
+ expect(partial.method(:example)).not_to be_nil
45
+ end
46
+ end
47
+
48
+ context "for an undefined method" do
49
+ it "returns false" do
50
+ instance = double("instance")
51
+ partial = Payload::PartialInstance.new(instance)
52
+
53
+ expect { partial.method(:unknown) }.to raise_error(NameError)
54
+ end
55
+ end
56
+ end
57
+ end
@@ -1,3 +1,11 @@
1
+ if ENV["CODECLIMATE_REPO_TOKEN"]
2
+ require "codeclimate-test-reporter"
3
+ CodeClimate::TestReporter.start
4
+ else
5
+ require "simplecov"
6
+ SimpleCov.start
7
+ end
8
+
1
9
  RSpec.configure do |config|
2
10
  config.raise_errors_for_deprecations!
3
11
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: payload
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - thoughtbot
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-11-03 00:00:00.000000000 Z
12
+ date: 2014-12-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rack
@@ -53,6 +53,20 @@ dependencies:
53
53
  - - "~>"
54
54
  - !ruby/object:Gem::Version
55
55
  version: 3.1.0
56
+ - !ruby/object:Gem::Dependency
57
+ name: codeclimate-test-reporter
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
56
70
  description: Dependency configuration and injection for Ruby and Rails.
57
71
  email: support@thoughtbot.com
58
72
  executables: []
@@ -63,12 +77,15 @@ extra_rdoc_files:
63
77
  - CONTRIBUTING.md
64
78
  files:
65
79
  - ".gitignore"
80
+ - ".travis.yml"
66
81
  - CONTRIBUTING.md
67
82
  - Gemfile
68
83
  - Gemfile.lock
69
84
  - LICENSE
70
85
  - README.md
71
86
  - Rakefile
87
+ - bin/rake
88
+ - bin/rspec
72
89
  - lib/payload/container.rb
73
90
  - lib/payload/controller.rb
74
91
  - lib/payload/decorator_chain.rb
@@ -79,6 +96,7 @@ files:
79
96
  - lib/payload/factory.rb
80
97
  - lib/payload/factory_resolver.rb
81
98
  - lib/payload/mutable_container.rb
99
+ - lib/payload/partial_instance.rb
82
100
  - lib/payload/rack_container.rb
83
101
  - lib/payload/rails_loader.rb
84
102
  - lib/payload/railtie.rb
@@ -97,6 +115,7 @@ files:
97
115
  - spec/payload/factory_resolver_spec.rb
98
116
  - spec/payload/factory_spec.rb
99
117
  - spec/payload/mutable_container_spec.rb
118
+ - spec/payload/partial_instance_spec.rb
100
119
  - spec/payload/rack_container_spec.rb
101
120
  - spec/payload/rails_loader_spec.rb
102
121
  - spec/payload/service_resolver_spec.rb
@@ -123,7 +142,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
123
142
  version: '0'
124
143
  requirements: []
125
144
  rubyforge_project:
126
- rubygems_version: 2.4.1
145
+ rubygems_version: 2.4.2
127
146
  signing_key:
128
147
  specification_version: 4
129
148
  summary: Dependency configuration and injection for Ruby and Rails.
@@ -137,6 +156,7 @@ test_files:
137
156
  - spec/payload/factory_resolver_spec.rb
138
157
  - spec/payload/factory_spec.rb
139
158
  - spec/payload/mutable_container_spec.rb
159
+ - spec/payload/partial_instance_spec.rb
140
160
  - spec/payload/rack_container_spec.rb
141
161
  - spec/payload/rails_loader_spec.rb
142
162
  - spec/payload/service_resolver_spec.rb