payload 0.2.2 → 0.3.0

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: 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