substation 0.0.9 → 0.0.10.beta2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +7 -0
  2. data/.travis.yml +0 -1
  3. data/Changelog.md +24 -82
  4. data/Gemfile.devtools +17 -24
  5. data/README.md +46 -116
  6. data/config/flay.yml +2 -2
  7. data/config/flog.yml +1 -1
  8. data/config/mutant.yml +0 -1
  9. data/config/reek.yml +5 -10
  10. data/lib/substation.rb +3 -8
  11. data/lib/substation/chain.rb +64 -108
  12. data/lib/substation/chain/dsl.rb +30 -57
  13. data/lib/substation/dispatcher.rb +1 -3
  14. data/lib/substation/environment.rb +23 -9
  15. data/lib/substation/environment/dsl.rb +3 -4
  16. data/lib/substation/observer.rb +2 -4
  17. data/lib/substation/processor.rb +7 -106
  18. data/lib/substation/processor/evaluator.rb +42 -83
  19. data/lib/substation/processor/pivot.rb +25 -0
  20. data/lib/substation/processor/wrapper.rb +2 -4
  21. data/lib/substation/request.rb +1 -10
  22. data/lib/substation/response.rb +0 -11
  23. data/lib/substation/utils.rb +1 -3
  24. data/lib/substation/version.rb +1 -3
  25. data/spec/integration/substation/dispatcher/call_spec.rb +12 -12
  26. data/spec/spec_helper.rb +21 -30
  27. data/spec/unit/substation/chain/call_spec.rb +32 -202
  28. data/spec/unit/substation/chain/dsl/builder/class_methods/call_spec.rb +2 -2
  29. data/spec/unit/substation/chain/dsl/builder/dsl_spec.rb +6 -8
  30. data/spec/unit/substation/chain/dsl/builder/failure_chain_spec.rb +30 -0
  31. data/spec/unit/substation/chain/dsl/chain_spec.rb +2 -1
  32. data/spec/unit/substation/chain/dsl/class_methods/processors_spec.rb +24 -0
  33. data/spec/unit/substation/chain/dsl/initialize_spec.rb +19 -0
  34. data/spec/unit/substation/chain/dsl/processors_spec.rb +21 -9
  35. data/spec/unit/substation/chain/dsl/use_spec.rb +3 -2
  36. data/spec/unit/substation/chain/each_spec.rb +9 -5
  37. data/spec/unit/substation/chain/incoming/result_spec.rb +21 -0
  38. data/spec/unit/substation/chain/outgoing/call_spec.rb +25 -0
  39. data/spec/unit/substation/{processor → chain/outgoing}/result_spec.rb +5 -6
  40. data/spec/unit/substation/dispatcher/action/call_spec.rb +6 -7
  41. data/spec/unit/substation/dispatcher/action/class_methods/coerce_spec.rb +5 -7
  42. data/spec/unit/substation/dispatcher/action_names_spec.rb +1 -1
  43. data/spec/unit/substation/dispatcher/call_spec.rb +3 -3
  44. data/spec/unit/substation/dispatcher/class_methods/coerce_spec.rb +7 -7
  45. data/spec/unit/substation/environment/chain_spec.rb +32 -22
  46. data/spec/unit/substation/environment/class_methods/build_spec.rb +4 -11
  47. data/spec/unit/substation/environment/dsl/class_methods/registry_spec.rb +3 -5
  48. data/spec/unit/substation/environment/dsl/register_spec.rb +3 -8
  49. data/spec/unit/substation/environment/dsl/registry_spec.rb +3 -5
  50. data/spec/unit/substation/observer/chain/call_spec.rb +3 -5
  51. data/spec/unit/substation/observer/class_methods/coerce_spec.rb +2 -4
  52. data/spec/unit/substation/observer/null/call_spec.rb +1 -3
  53. data/spec/unit/substation/processor/evaluator/call_spec.rb +35 -21
  54. data/spec/unit/substation/processor/pivot/call_spec.rb +17 -0
  55. data/spec/unit/substation/processor/wrapper/call_spec.rb +7 -8
  56. data/spec/unit/substation/request/env_spec.rb +4 -5
  57. data/spec/unit/substation/request/error_spec.rb +4 -5
  58. data/spec/unit/substation/request/input_spec.rb +4 -5
  59. data/spec/unit/substation/request/success_spec.rb +4 -5
  60. data/spec/unit/substation/response/env_spec.rb +5 -6
  61. data/spec/unit/substation/response/failure/success_predicate_spec.rb +4 -5
  62. data/spec/unit/substation/response/input_spec.rb +5 -6
  63. data/spec/unit/substation/response/output_spec.rb +4 -5
  64. data/spec/unit/substation/response/request_spec.rb +5 -6
  65. data/spec/unit/substation/response/success/success_predicate_spec.rb +4 -5
  66. data/spec/unit/substation/utils/class_methods/coerce_callable_spec.rb +13 -15
  67. data/spec/unit/substation/utils/class_methods/const_get_spec.rb +6 -6
  68. data/spec/unit/substation/utils/class_methods/symbolize_keys_spec.rb +4 -4
  69. data/substation.gemspec +1 -1
  70. metadata +18 -45
  71. data/config/rubocop.yml +0 -35
  72. data/lib/substation/processor/transformer.rb +0 -26
  73. data/spec/unit/substation/chain/class_methods/failure_response_spec.rb +0 -16
  74. data/spec/unit/substation/chain/dsl/class_methods/build_spec.rb +0 -24
  75. data/spec/unit/substation/chain/dsl/failure_chain_spec.rb +0 -35
  76. data/spec/unit/substation/chain/failure_data/equalizer_spec.rb +0 -46
  77. data/spec/unit/substation/chain/failure_data/hash_spec.rb +0 -13
  78. data/spec/unit/substation/environment/equalizer_spec.rb +0 -25
  79. data/spec/unit/substation/processor/evaluator/class_methods/new_spec.rb +0 -9
  80. data/spec/unit/substation/processor/evaluator/data/call_spec.rb +0 -34
  81. data/spec/unit/substation/processor/evaluator/pivot/call_spec.rb +0 -34
  82. data/spec/unit/substation/processor/evaluator/request/call_spec.rb +0 -34
  83. data/spec/unit/substation/processor/fallible/name_spec.rb +0 -15
  84. data/spec/unit/substation/processor/fallible/with_failure_chain_spec.rb +0 -18
  85. data/spec/unit/substation/processor/incoming/result_spec.rb +0 -25
  86. data/spec/unit/substation/processor/outgoing/call_spec.rb +0 -28
  87. data/spec/unit/substation/processor/outgoing/name_spec.rb +0 -14
  88. data/spec/unit/substation/processor/outgoing/success_predicate_spec.rb +0 -15
  89. data/spec/unit/substation/processor/success_predicate_spec.rb +0 -22
  90. data/spec/unit/substation/processor/transformer/call_spec.rb +0 -21
  91. data/spec/unit/substation/request/name_spec.rb +0 -15
  92. data/spec/unit/substation/response/to_request_spec.rb +0 -19
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 674a347348ff4f36dbca255925b70c9ea794c95d
4
+ data.tar.gz: a28efb6f4038ee99e8f820f2dcaee74506e4182b
5
+ SHA512:
6
+ metadata.gz: 5a9dcabb1d4a225cee6a4579587387c3829747fcaf77319ae2a0c2a2863eae6558c4d825e6c48f59ecc7d2a860831ae8dcadcda053d947f431b9b73bbaa0c593
7
+ data.tar.gz: bbd1fca2660e54697b3d1d8f5a69e4a527cf5a129a0995e589cf99966d7c54f9a10b30313e3f51b91a60b4ea38443dcb0a5f3e68253e028ffcda4804def5d107
data/.travis.yml CHANGED
@@ -12,4 +12,3 @@ rvm:
12
12
  matrix:
13
13
  allow_failures:
14
14
  - rvm: ruby-head
15
- - rvm: rbx-19mode
data/Changelog.md CHANGED
@@ -1,98 +1,40 @@
1
- # v0.0.10 (not yet released)
1
+ # v0.0.9 (not yet released)
2
2
 
3
- *
3
+ * [feature] Support definining failure chains
4
4
 
5
- [Compare v0.0.9..master](https://github.com/snusnu/substation/compare/v0.0.9...master)
6
-
7
- # v0.0.9 2013-07-10
8
-
9
- * [BREAKING CHANGE] Refactor `Substation::Processor` classes.
10
-
11
- * Renamed `Substation::Processor::Evaluator` to `Substation::Processor::Evaluator::Data`.
12
- * Renamed `Substation::Processor::Pivot` to `Substation::Processor::Evaluator::Pivot`.
13
- * Added `Substation::Processor::Evaluator::Request` which passes the complete `Request` instance on to the handler.
14
- * Added `Substation::Processor::Transformer` to transform `Response#output` into any other object.
15
-
16
- * [feature] Make the dispatched name available in `Request#name`.
17
-
18
- * [feature] Support (re)definining failure chains for `Substation::Processor::Fallible` processors.
19
-
20
- module Demo
21
- ENV = Substation::Environment.build do
22
- register :validate, Substation::Processor::Evaluator::Data
23
- register :call, Substation::Processor::Evaluator::Pivot
24
- register :wrap, Substation::Processor::Wrapper
25
- register :render, Substation::Processor::Transformer
26
- end
27
-
28
- class Error
29
- attr_reader :data
30
- def initialize(data)
31
- @data = data
32
- end
33
-
34
- ValidationError = Class.new(self)
35
- ApplicationError = Class.new(self)
36
- InternalError = Class.new(self)
37
- end
38
-
39
- module App
40
- VALIDATION_ERROR = Demo::ENV.chain { wrap Error::ValidationError }
41
- APPLICATION_ERROR = Demo::ENV.chain { wrap Error::ApplicationError }
5
+ env = Substation::Environment.build do
6
+ register :evaluate, Substation::Processor::Evaluator
7
+ register :wrap, Substation::Processor::Wrapper
8
+ end
42
9
 
43
- SOME_ACTION = Demo::ENV.chain do
44
- validate Vanguard::Validator, VALIDATION_ERROR
45
- call Some::Action, APPLICATION_ERROR
46
- end
10
+ class Error
11
+ attr_reader :data
12
+ def initialize(data)
13
+ @data = data
47
14
  end
48
15
 
49
- module Web
50
- VALIDATION_ERROR = Demo::ENV.chain(App::VALIDATION_ERROR) do
51
- render Renderer::ValidationError
52
- end
53
-
54
- APPLICATION_ERROR = Demo::ENV.chain(App::APPLICATION_ERROR) do
55
- render Renderer::ApplicationError
56
- end
57
-
58
- # in case of success, returns an instance of Views::Person
59
- # in case of validation failure, renders using Renderer::ValidationError
60
- # in case of internal error, renders using Renderer::InternalError
61
- SOME_ACTION = Demo::ENV.chain(App::SOME_ACTION) do
62
- failure_chain :validate, VALIDATION_ERROR
63
- failure_chain :call, INTERNAL_ERROR
64
- wrap Presenters::Person
65
- wrap Views::ShowPerson
66
- end
16
+ class ValidationError < self
67
17
  end
68
18
  end
69
19
 
70
- * [feature] Support (re)defining chain specific failure chains in case of uncaught exceptions.
71
-
72
- module Demo
73
-
74
- module App
75
- INTERNAL_ERROR = Demo::ENV.chain { wrap Error::InternalError }
20
+ chain = env.chain do
21
+ evaluate Vanguard::Validator do
22
+ wrap Errors::ValidationError
76
23
  end
24
+ call Some::Action
25
+ wrap Some::Presenter
26
+ end
77
27
 
78
- module Web
28
+ env = Object.new
29
+ invalid_request = Substation::Requet.new(env, :invalid)
30
+ response = chain.call(invalid_request)
79
31
 
80
- INTERNAL_ERROR = Demo::ENV.chain(App::INTERNAL_ERROR) do
81
- render Renderer::InternalError
82
- end
32
+ response.data.instance_of?(Errors::ValidationError)
33
+ # => true
83
34
 
84
- # The INTERNAL_ERROR chain will be called if an exception
85
- # isn't rescued by the responsible handler
86
- SOME_ACTION = Demo::ENV.chain(App::SOME_ACTION, INTERNAL_ERROR) do
87
- failure_chain :validate, VALIDATION_ERROR
88
- failure_chain :call, INTERNAL_ERROR
89
- wrap Presenters::Person
90
- wrap Views::ShowPerson
91
- end
92
- end
93
- end
35
+ response.data.data # => the actual vanguard violation set
94
36
 
95
- [Compare v0.0.8..v0.0.9](https://github.com/snusnu/substation/compare/v0.0.8...v0.0.9)
37
+ [Compare v0.0.8..master](https://github.com/snusnu/substation/compare/v0.0.8...master)
96
38
 
97
39
  # v0.0.8 2013-06-19
98
40
 
data/Gemfile.devtools CHANGED
@@ -2,12 +2,12 @@
2
2
 
3
3
  group :development do
4
4
  gem 'rake', '~> 10.1.0'
5
- gem 'rspec', '~> 2.13.0'
6
- gem 'yard', '~> 0.8.6.2'
5
+ gem 'rspec', '~> 2.14.1'
6
+ gem 'yard', '~> 0.8.7'
7
7
  end
8
8
 
9
9
  group :yard do
10
- gem 'kramdown', '~> 1.1.0'
10
+ gem 'kramdown', '~> 1.2.0'
11
11
  end
12
12
 
13
13
  group :guard do
@@ -15,40 +15,33 @@ group :guard do
15
15
  gem 'guard-bundler', '~> 1.0.0'
16
16
  gem 'guard-rspec', '~> 3.0.2'
17
17
  gem 'guard-rubocop', '~> 0.2.0'
18
+ gem 'guard-mutant', '~> 0.0.1'
18
19
 
19
20
  # file system change event handling
20
- gem 'listen', '~> 1.2.2'
21
- gem 'rb-fchange', '~> 0.0.6', :require => false
22
- gem 'rb-fsevent', '~> 0.9.3', :require => false
23
- gem 'rb-inotify', '~> 0.9.0', :require => false
21
+ gem 'listen', '~> 1.3.0'
22
+ gem 'rb-fchange', '~> 0.0.6', require: false
23
+ gem 'rb-fsevent', '~> 0.9.3', require: false
24
+ gem 'rb-inotify', '~> 0.9.0', require: false
24
25
 
25
26
  # notification handling
26
- gem 'libnotify', '~> 0.8.0', :require => false
27
- gem 'rb-notifu', '~> 0.0.4', :require => false
28
- gem 'terminal-notifier-guard', '~> 1.5.3', :require => false
27
+ gem 'libnotify', '~> 0.8.0', require: false
28
+ gem 'rb-notifu', '~> 0.0.4', require: false
29
+ gem 'terminal-notifier-guard', '~> 1.5.3', require: false
29
30
  end
30
31
 
31
32
  group :metrics do
32
33
  gem 'coveralls', '~> 0.6.7'
33
- gem 'flay', '~> 2.3.0'
34
- gem 'flog', '~> 4.1.0'
35
- gem 'reek', '~> 1.3.1', :git => 'https://github.com/troessner/reek.git'
36
- gem 'rubocop', '~> 0.9.1'
34
+ gem 'flay', '~> 2.4.0'
35
+ gem 'flog', '~> 4.1.1'
36
+ gem 'reek', '~> 1.3.2'
37
+ gem 'rubocop', '~> 0.13.0'
37
38
  gem 'simplecov', '~> 0.7.1'
38
- gem 'yardstick', '~> 0.9.6'
39
+ gem 'yardstick', '~> 0.9.7', git: 'https://github.com/dkubb/yardstick.git'
39
40
 
40
41
  platforms :ruby_19, :ruby_20 do
41
- gem 'mutant', '~> 0.3.0.beta13'
42
+ gem 'mutant', git: 'https://github.com/mbj/mutant.git'
42
43
  gem 'yard-spellcheck', '~> 0.1.5'
43
44
  end
44
-
45
- platforms :ruby_19 do
46
- gem 'json', '~> 1.8.0'
47
- end
48
-
49
- platforms :rbx do
50
- gem 'pelusa', '~> 0.2.2'
51
- end
52
45
  end
53
46
 
54
47
  group :benchmarks do
data/README.md CHANGED
@@ -22,8 +22,7 @@ receive arbitrary input data which will be available in `request.input`.
22
22
  Additionally, `request.env` contains an arbitrary object that
23
23
  represents your application environment and will typically provide access
24
24
  to useful things like a logger and probably some sort of storage engine
25
- abstraction object. Furthermore, `request.name` will contain the action
26
- name the `Substation::Dispatcher` used when dispatching to an action.
25
+ abstraction object.
27
26
 
28
27
  The contract further specifies that every action must return an instance
29
28
  of either `Substation::Response::Success` or
@@ -510,9 +509,9 @@ In a typical application scenario, a few things need to happen before an
510
509
  actual use case (an action) can be invoked. These things will often
511
510
  include the following steps (probably in that order).
512
511
 
513
- * Input data sanitization
514
512
  * Authentication
515
513
  * Authorization
514
+ * Input data sanitization
516
515
  * Input data validation
517
516
 
518
517
  We only want to invoke our action if all those steps succeed. If any of
@@ -542,198 +541,129 @@ b) If you need to return JSON, you might just
542
541
  * Pass the response data to some serializer object and dump it to JSON
543
542
 
544
543
  To allow chaining all those steps in a declarative way, substation
545
- provides an object called `Substation::Chain`. To construct a chain, you
546
- need to pass an enumerable of processors to `Substation::Chain#initialize`.
547
- Processors must support three methods:
544
+ provides an object called `Substation::Chain`. Its contract is dead
545
+ simple:
546
+
547
+ 1. `#call(Substation::Request) => Substation::Response`
548
+ 2. `#result(Substation::Response) => Substation::Response`
549
+
550
+ You typically won't be calling `Substation::Chain#result` yourself, but
551
+ having it around, allows us to use chains in *incoming handlers*,
552
+ essentially nesting chains. This makes it possible to construct one
553
+ chain up until the pivot handler, and then reuse that same chain in one
554
+ usecase that takes the response and renders HTML, and in another that
555
+ renders JSON.
556
+
557
+ To construct a chain, you need to pass an enumerable of so called
558
+ handler objects to `Substation::Chain.new`. Handlers must support two
559
+ methods:
548
560
 
549
561
  1. `#call(<Substation::Request, Substation::Response>) => Substation::Response`
550
562
  2. `#result(Substation::Response) => <Substation::Request, Substation::Response>`
551
- 3. `#success?(Substation::Response) => Boolean`
552
563
 
553
- ### Incoming processors
564
+ ### Incoming handlers
554
565
 
555
566
  All steps required *before* processing the action will potentially
556
567
  produce a new, altered, `Substation::Request`. Therefore, the object
557
568
  passed to `#call` must be an instance of `Substation::Request`.
558
569
 
559
570
  Since `#call` must return a `Substation::Response` (because the chain
560
- would halt and return that response in case calling `Processor#success?`
571
+ would halt and return that response in case calling its `#success?`
561
572
  method would return `false`), we also need to implement `#result`
562
573
  and have it return a `Substation::Request` instance that can be passed
563
574
  on to the next handler.
564
575
 
565
- The contract for incoming processors therefore is:
576
+ The contract for incoming handlers therefore is:
566
577
 
567
578
  1. `#call(Substation::Request) => Substation::Response`
568
579
  2. `#result(Substation::Response) => Substation::Request`
569
- 3. `#success?(Substation::Response) => Boolean`
570
580
 
571
- By including the `Substation::Processor::Incoming` module into your
572
- processor class, you'll get the following for free:
581
+ By including the `Substation::Chain::Incoming` module into your handler
582
+ class, you'll get the following for free:
573
583
 
574
584
  ```ruby
575
- def initialize(name, handler, failure_chain)
576
- @name, @handler, @failure_chain = name, handler, failure_chain
577
- end
578
-
579
585
  def result(response)
580
- response.to_request
581
- end
582
-
583
- def success?(response)
584
- response.success?
585
- end
586
-
587
- def with_failure_chain(chain)
588
- self.class.new(name, handler, chain)
586
+ Request.new(response.env, response.output)
589
587
  end
590
588
  ```
591
589
 
592
- This shows that an incoming processor can alter the incoming request in any
590
+ This shows that an incoming handler can alter the incoming request in any
593
591
  way that it wants to, as long as it returns the new request input data in
594
592
  `Substation::Response#output` returned from `#call`.
595
593
 
596
- Currently, `substation` provides the following incoming processors out
597
- of the box:
598
-
599
- * `Substation::Processor::Evaluator::Request` passes `request` to the handler
600
- * `Substation::Processor::Evaluator::Data` passes `request.input` to the handler
601
-
602
- ### The pivot processor
594
+ ### The pivot handler
603
595
 
604
596
  Pivot is just another fancy name for the action in the context of a
605
- chain. It's also the point where all subsequent processors have to further
597
+ chain. It's also the point where all subsequent handlers have to further
606
598
  process the `Substation::Response` returned from invoking the action.
607
- Therefore, the pivot processor is the last processor that expects a
608
- `Substation::Request` as parameter to its `#call` method.
609
599
 
610
- The contract for the pivot processor therefore is:
600
+ The contract for the pivot handler therefore is:
611
601
 
612
602
  1. `#call(Substation::Request) => Substation::Response`
613
603
  2. `#result(Substation::Response) => Substation::Response`
614
- 3. `#success?(Substation::Response) => Boolean`
615
604
 
616
- By including the `Substation::Processor::Pivot` module into your handler
605
+ By including the `Substation::Chain::Pivot` module into your handler
617
606
  class, you'll get the following for free:
618
607
 
619
608
  ```ruby
620
- def initialize(name, handler, failure_chain)
621
- @name, @handler, @failure_chain = name, handler, failure_chain
622
- end
623
-
624
609
  def result(response)
625
610
  response
626
611
  end
627
-
628
- def success?(response)
629
- response.success?
630
- end
631
-
632
- def with_failure_chain(chain)
633
- self.class.new(name, handler, chain)
634
- end
635
612
  ```
636
613
 
637
- This reflects the fact that a pivot processor (since it's the one actually
638
- producing the "raw" response, returns it unaltered).
639
-
640
- The pivot processor is shipped with `substation` and is implemented by
641
- `Substation::Processor::Evaluator::Pivot`.
614
+ This reflects the fact that a pivot handler (since it's the one actually
615
+ producing the "raw" response, returns it unaltered.
642
616
 
643
- ### Outgoing processors
617
+ ### Outgoing handlers
644
618
 
645
619
  All steps required *after* processing the action will potentially
646
620
  produce a new, altered, `Substation::Response` instance to be returned.
647
621
  Therefore the object passed to `#call` must be an instance of
648
- `Substation::Response`. Since subsequent outgoing processors might further
622
+ `Substation::Response`. Since subsequent outgoing handlers might further
649
623
  process the response, `#result` must be implemented so that it returns a
650
- `Substation::Response` object that can be passed on to the next
651
- processor.
624
+ `Substation::Response` object that can be passed on to the next handler.
652
625
 
653
- The contract for outgoing processors therefore is:
626
+ The contract for outgoing handlers therefore is:
654
627
 
655
628
  1. `#call(Substation::Response) => Substation::Response`
656
629
  2. `#result(Substation::Response) => Substation::Response`
657
- 3. `#success?(Substation::Response) => true`
658
630
 
659
- By including the `Substation::Processor::Outgoing` module into your
660
- processor class, you'll get the following for free:
631
+ By including the `Substation::Chain::Outgoing` module into your handler
632
+ class, you'll get the following for free:
661
633
 
662
634
  ```ruby
663
- def initialize(name, handler)
664
- @name, @handler = name, handler
665
- end
666
-
667
635
  def result(response)
668
636
  response
669
637
  end
670
-
671
- def success?(response)
672
- true
673
- end
674
-
675
- private
676
-
677
- def respond_with(response, output)
678
- response.class.new(response.request, output)
679
- end
680
638
  ```
681
639
 
682
- This shows that an outgoing processor's `#call` can do anything with
640
+ This shows that an outgoing handler's `#call` can do anything with
683
641
  the `Substation::Response#output` it received, as long as it makes
684
642
  sure to return a new response with the new output properly set.
685
643
 
686
- Currently, `substation` provides the following outgoing processors out
687
- of the box:
688
-
689
- * `Substation::Processor::Wrapper` wraps `response.output` in a new handler instance
690
- * `Substation::Processor::Transformer` transforms `response.output` using a new handler instance
691
-
692
- ### Handlers
693
-
694
- You might have noticed the `handler` param passed to any processor's
695
- `#initialize` method. Handlers are the actual objects performing your
696
- application logic. Processors use these handlers to produce the data
697
- they're supposed to "pipe through the chain".
698
-
699
- The interface your handlers must implement should be familiar by now.
700
-
701
- All handlers to be used with incoming processors must accept an instance
702
- of `Substation::Request` as parameter to `#call`. Handlers to be used
703
- with `Substation::Processor::Evaluator` subclasses must furthermore
704
- return an object that responds to `#success?` and `#output`.
705
-
706
- Note how the interface required for evaluator handler return values
707
- matches the interface a `Substation::Response` exposes. This means that
708
- the pivot processor can be (and is) implemented using the builtin
709
- `Substation::Processor::Evaluator::Request` processor. The handler you
710
- pass to the pivot processor is the object that actually implements your
711
- application usecase, the action, and it's response gets evaluated.
712
-
713
- All handlers to be used with outgoing processors must accept an instance
714
- of `Substation::Response` as parameter to `#call`. They can do whatever
715
- they want with the passed in response, but they must make sure to return
716
- another instance of `Substation::Response`. To help with this, outgoing
717
- processors provide the `#respond_with(response, data)` method that
718
- you'll typically call to return the response value for `#call`.
719
-
720
644
  ### Example
721
645
 
722
646
  [substation-demo](https://github.com/snusnu/substation-demo) implements a
723
647
  simple web application using `Substation::Chain`.
724
648
 
725
- The demo uses a few of the above mentioned *incoming processors*
649
+ The demo implements a few of the above mentioned *incoming handlers*
726
650
  for
727
651
 
728
652
  * [Sanitization](https://github.com/snusnu/substation-demo/blob/master/demo/web/sanitizers.rb) using [ducktrap](https://github.com/mbj/ducktrap)
729
653
  * [Validation](https://github.com/snusnu/substation-demo/blob/master/demo/validators.rb) using [vanguard](https://github.com/mbj/vanguard)
730
654
 
731
- and some simple *outgoing processors* for
655
+ and some simple *outgoing handlers* for
732
656
 
733
657
  * Wrapping response output in a
734
658
  [presenter](https://github.com/snusnu/substation-demo/blob/master/demo/web/presenters.rb)
735
659
  * [Serializing](https://github.com/snusnu/substation-demo/blob/master/demo/web/serializers.rb) response output to JSON
736
660
 
661
+ The
662
+ [handlers](https://github.com/snusnu/substation-demo/blob/master/demo/web/processors.rb)
663
+ are called *processors* in that app, and encapsulate the actual handler
664
+ performing the job. That's a common pattern, because you typically will
665
+ have to adapt to the interface your actual handlers provide.
666
+
737
667
  Have a look at the base
738
668
  [actions](https://github.com/snusnu/substation-demo/blob/master/demo/web/actions.rb)
739
669
  that are then used to either produce