web_pipe 0.13.0 → 0.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +4 -1
  3. data/CHANGELOG.md +29 -0
  4. data/Gemfile +2 -2
  5. data/README.md +18 -11
  6. data/docs/building_a_rack_application.md +1 -1
  7. data/docs/composing_applications.md +4 -4
  8. data/docs/connection_struct/configuring_the_connection_struct.md +4 -4
  9. data/docs/connection_struct/halting_the_pipe.md +17 -19
  10. data/docs/connection_struct/sharing_data_downstream.md +9 -8
  11. data/docs/connection_struct.md +22 -19
  12. data/docs/design_model.md +10 -9
  13. data/docs/dsl_free_usage.md +85 -14
  14. data/docs/extensions/container.md +9 -10
  15. data/docs/extensions/cookies.md +4 -2
  16. data/docs/extensions/dry_schema.md +5 -4
  17. data/docs/extensions/flash.md +9 -11
  18. data/docs/extensions/{dry_view.md → hanami_view.md} +20 -22
  19. data/docs/extensions/not_found.md +40 -0
  20. data/docs/extensions/params.md +6 -4
  21. data/docs/extensions/rails.md +31 -38
  22. data/docs/extensions/redirect.md +5 -4
  23. data/docs/extensions/router_params.md +5 -5
  24. data/docs/extensions/session.md +4 -4
  25. data/docs/extensions/url.md +6 -6
  26. data/docs/extensions.md +5 -6
  27. data/docs/introduction.md +7 -7
  28. data/docs/plugging_operations/composing_operations.md +3 -3
  29. data/docs/plugging_operations/injecting_operations.md +4 -4
  30. data/docs/plugging_operations/inspecting_operations.md +24 -0
  31. data/docs/plugging_operations/resolving_operations.md +3 -3
  32. data/docs/plugging_operations.md +3 -3
  33. data/docs/plugs/config.md +1 -1
  34. data/docs/plugs/content_type.md +2 -1
  35. data/docs/plugs.md +6 -7
  36. data/docs/recipes/hanami_2_and_dry_rb_integration.md +12 -0
  37. data/docs/recipes/hanami_router_integration.md +3 -1
  38. data/docs/recipes/using_all_restful_methods.md +6 -5
  39. data/docs/testing.md +64 -0
  40. data/docs/using_rack_middlewares/composing_middlewares.md +2 -3
  41. data/docs/using_rack_middlewares/injecting_middlewares.md +6 -6
  42. data/docs/using_rack_middlewares/inspecting_middlewares.md +35 -0
  43. data/docs/using_rack_middlewares.md +6 -6
  44. data/lib/web_pipe/app.rb +22 -25
  45. data/lib/web_pipe/conn.rb +0 -1
  46. data/lib/web_pipe/conn_support/builder.rb +0 -7
  47. data/lib/web_pipe/conn_support/composition.rb +3 -26
  48. data/lib/web_pipe/conn_support/errors.rb +5 -5
  49. data/lib/web_pipe/conn_support/headers.rb +1 -50
  50. data/lib/web_pipe/conn_support/types.rb +3 -3
  51. data/lib/web_pipe/dsl/builder.rb +10 -19
  52. data/lib/web_pipe/dsl/class_context.rb +15 -40
  53. data/lib/web_pipe/dsl/instance_context.rb +53 -0
  54. data/lib/web_pipe/extensions/container/container.rb +2 -15
  55. data/lib/web_pipe/extensions/cookies/cookies.rb +2 -31
  56. data/lib/web_pipe/extensions/dry_schema/dry_schema.rb +2 -56
  57. data/lib/web_pipe/extensions/flash/flash.rb +2 -32
  58. data/lib/web_pipe/extensions/hanami_view/hanami_view.rb +67 -0
  59. data/lib/web_pipe/extensions/not_found/not_found.rb +26 -0
  60. data/lib/web_pipe/extensions/params/params.rb +2 -63
  61. data/lib/web_pipe/extensions/rails/rails.rb +2 -123
  62. data/lib/web_pipe/extensions/redirect/redirect.rb +2 -20
  63. data/lib/web_pipe/extensions/router_params/router_params.rb +1 -39
  64. data/lib/web_pipe/extensions/session/session.rb +2 -25
  65. data/lib/web_pipe/extensions/url/url.rb +2 -5
  66. data/lib/web_pipe/pipe.rb +229 -0
  67. data/lib/web_pipe/plug.rb +31 -65
  68. data/lib/web_pipe/plugs/config.rb +0 -2
  69. data/lib/web_pipe/plugs/content_type.rb +0 -2
  70. data/lib/web_pipe/rack_support/app_with_middlewares.rb +3 -26
  71. data/lib/web_pipe/rack_support/middleware.rb +2 -2
  72. data/lib/web_pipe/rack_support/middleware_specification.rb +19 -48
  73. data/lib/web_pipe/test_support.rb +28 -0
  74. data/lib/web_pipe/types.rb +1 -3
  75. data/lib/web_pipe/version.rb +1 -1
  76. data/lib/web_pipe.rb +77 -17
  77. data/web_pipe.gemspec +1 -2
  78. metadata +16 -9
  79. data/docs/recipes/dry_rb_integration.md +0 -18
  80. data/lib/web_pipe/dsl/dsl_context.rb +0 -85
  81. data/lib/web_pipe/dsl/instance_methods.rb +0 -114
  82. data/lib/web_pipe/extensions/dry_view/dry_view.rb +0 -158
@@ -1,21 +1,23 @@
1
- # Dry View
1
+ # Hanami View
2
2
 
3
- This extensions integrates with
4
- [dry-view](https://dry-rb.org/gems/dry-view/) rendering system to
5
- set a dry-view output as response body.
3
+ This extension currently works with `hanami-view` v2.0.0.alpha2, which is not
4
+ still released but available on the gem repository.
5
+
6
+ This extension integrates with [hanami-view](https://github.com/hanami/view)
7
+ rendering system to set a hanami-view output as the response body.
6
8
 
7
9
  `WebPipe::Conn#view` method is at the core of this extension. In its basic
8
- behaviour, you provide to it a view instance you want to render and any
10
+ behavior, you provide to it a view instance you want to render and any
9
11
  exposures or options it may need:
10
12
 
11
13
  ```ruby
12
14
  require 'web_pipe'
13
- require 'dry/view'
15
+ require 'hanami/view'
14
16
  require 'my_context'
15
17
 
16
- WebPipe.load_extensions(:dry_view)
18
+ WebPipe.load_extensions(:hanami_view)
17
19
 
18
- class SayHelloView < Dry::View
20
+ class SayHelloView < Hanami::View
19
21
  config.paths = [File.join(__dir__, '..', 'templates')]
20
22
  config.template = 'say_hello'
21
23
  config.default_context = MyContext
@@ -35,17 +37,16 @@ class MyApp
35
37
  end
36
38
  end
37
39
  ```
38
-
39
- However, you can resolve a view from a container if you also use (`:container`
40
- extension)[container.md]:
40
+ However, you can resolve a view from a container if you also use the
41
+ (`:container` extension)[container.md]:
41
42
 
42
43
  ```ruby
43
- require 'dry_view'
44
+ require 'hanami_view'
44
45
  require 'my_container'
45
46
  require 'web_pipe'
46
47
  require 'web_pipe/plugs/config'
47
48
 
48
- WebPipe.load_extensions(:dry_view, :container)
49
+ WebPipe.load_extensions(:hanami_view, :container)
49
50
 
50
51
  class MyApp
51
52
  include WebPipe
@@ -61,20 +62,17 @@ class MyApp
61
62
  end
62
63
  ```
63
64
 
64
- As in a standard call to `Dry::View#call`, you can override the context
65
- (`Dry::View::Context`) to use through `context:` option. However, it is still
66
- possible to leverage configured default context while being able to inject
67
- request specific data to it.
65
+ As in a standard call to `Hanami::View#call`, you can override the context
66
+ (`Hanami::View::Context`) to use through the `context:` option. However, it is still possible to leverage the configured default context while injecting specific data to it.
68
67
 
69
- For that to work, you have to specify required dependencies (in this case,
70
- request specific data) to your dry-view's context. A very convenient way to do
71
- that is with [`dry-auto_inject`](https://dry-rb.org/gems/dry-auto_inject):
68
+ To work, you have to specify required dependencies (in this case,
69
+ request specific data) to your hanami-view's context. A very convenient way to do that is with [`dry-auto_inject`](https://dry-rb.org/gems/dry-auto_inject):
72
70
 
73
71
  ```ruby
74
- require 'dry/view/context'
72
+ require 'hanami/view/context'
75
73
  require 'my_import'
76
74
 
77
- class MyContext < Dry::View::Context
75
+ class MyContext < Hanami::View::Context
78
76
  include MyImport::Import[:current_path]
79
77
 
80
78
  # Without `dry-auto_inject` you have to manually specify dependencies and
@@ -0,0 +1,40 @@
1
+ # Not found
2
+
3
+ This extension helps to build a not-found response in a single method
4
+ invocation. The `WebPipe::Conn#not_found` method will:
5
+
6
+ - Set 404 as response status.
7
+ - Set 'Not found' as the response body, or instead run a step configured in
8
+ `:not_found_body_step` config key.
9
+ - Halt the connection struct.
10
+
11
+ ```ruby
12
+ require 'web_pipe'
13
+ require 'web_pipe/plugs/config'
14
+
15
+ WebPipe.load_extensions(:params, :not_found)
16
+
17
+ class ShowItem
18
+ include 'web_pipe'
19
+
20
+ plug :config, WebPipe::Plugs::Config.(
21
+ not_found_body_step: ->(conn) { conn.set_response_body('Nothing') }
22
+ )
23
+
24
+ plug :fetch_item do |conn|
25
+ conn.add(:item, Item[params['id']])
26
+ end
27
+
28
+ plug :check_item do |conn|
29
+ if conn.fetch(:item)
30
+ conn
31
+ else
32
+ conn.not_found
33
+ end
34
+ end
35
+
36
+ plug :render do |conn|
37
+ conn.set_response_body(conn.fetch(:item).name)
38
+ end
39
+ end
40
+ ```
@@ -1,10 +1,11 @@
1
1
  # Params
2
2
 
3
3
  This extension adds a `WebPipe::Conn#params` method which returns
4
- request parameters as a Hash where any number of transformations
5
- can be configured.
4
+ request parameters as a Hash. Then, any number of transformations on it can be
5
+ configured.
6
6
 
7
- When no transformations are configured, `#params` just returns GET and POST parameters as a hash:
7
+ When no transformations are configured, `#params` returns GET and POST
8
+ parameters as a hash:
8
9
 
9
10
  ```ruby
10
11
  # http://www.example.com?foo=bar
@@ -102,7 +103,8 @@ plug(:this) do |conn|
102
103
  end
103
104
  # ...
104
105
  ```
105
- Finally, you can override configured transformations injecting another set at the moment of calling `#params`:
106
+ Finally, you can override the configured transformations injecting another set
107
+ at the moment of calling `#params`:
106
108
 
107
109
  ```ruby
108
110
  # ...
@@ -1,8 +1,8 @@
1
1
  # Rails
2
2
 
3
- The first two things to keep in mind in order to integrate with Rails is
3
+ The first two things to keep in mind to integrate with Rails are
4
4
  that `WebPipe` instances are Rack applications and that rails router can
5
- perfectly [dispatch to a rack application](https://guides.rubyonrails.org/routing.html#routing-to-rack-applications). For example:
5
+ perfectly [dispatch to a rack application](https://guides.rubyonrails.org/routing.html#routing-to-rack-applications).
6
6
 
7
7
  ```ruby
8
8
  # config/routes.rb
@@ -22,31 +22,29 @@ class MyRoute
22
22
  end
23
23
  ```
24
24
 
25
- In order to do something like the previous example you don't need to enable
26
- this extension. Notice that rails took care of dispatching the request to our
27
- `WebPipe` rack application, which was then responsible for generating the
28
- response. In this case, it used a simple call to `#set_response_body`.
25
+ To do something like the previous example, you don't need to enable this
26
+ extension. Notice that rails dispatched the request to our `WebPipe` rack
27
+ application, which was then responsible for generating the response. In this
28
+ case, it used a simple call to `#set_response_body`.
29
29
 
30
30
  It's quite possible that you don't need more than that in terms of rails
31
- integration. Of course, surely you want something more elaborate to generate
31
+ integration. Of course, you want something more elaborate to generate
32
32
  responses. For that, you can use the view or template system you like. One
33
- option that will play specially well here is
34
- [`dry-view`](https://dry-rb.org/gems/dry-view/), which
35
- [integrates](https://github.com/dry-rb/dry-view/tree/master/examples/rails)
36
- itself easily with Rails. Furthermore, we have a tailored `dry_view`
37
- [extension](https://waiting-for-dev.github.io/web_pipe/docs/extensions/dry_view.html).
33
+ option that will play especially well here is
34
+ [`hanami-view`](https://github.com/hanami/view). Furthermore, we have a
35
+ tailored `hanami_view`
36
+ [extension](https://waiting-for-dev.github.io/web_pipe/docs/extensions/hanami_view.html).
38
37
 
39
- You need to use `:rails` extension if:
38
+ You need to use the `:rails` extension if:
40
39
 
41
- - You want to use `action_view` as rendering system.
42
- - You want to use rails url helpers from your `WebPipe` application.
40
+ - You want to use `action_view` as a rendering system.
41
+ - You want to use rails URL helpers from your `WebPipe` application.
43
42
  - You want to use controller helpers from your `WebPipe` application.
44
43
 
45
- Rails responsibilities for controlling the request/response cycle and the
46
- rendering process are a little bit tangled. For this reason, even if you
47
- want to use `WebPipe` applications instead of Rails controller actions you
48
- still have to use the typical top `ApplicationController` in order to define
49
- some behaviour for the view layer:
44
+ Rails' responsibilities for controlling the request/response cycle are coupled
45
+ to the rendering process. For this reason, even if you want to use `WebPipe`
46
+ applications instead of Rails controller actions you still have to use the
47
+ typical top `ApplicationController` to define some behavior for the view layer:
50
48
 
51
49
  - Which layout is applied to the template.
52
50
  - Which helpers will become available to the templates.
@@ -56,11 +54,11 @@ no layout is applied and only built-in helpers (for example,
56
54
  `number_as_currency`) are available. You can change it via the
57
55
  `:rails_controller` configuration option.
58
56
 
59
- The main method that this extension adds to `WebPipe::Conn` is `#render`,
60
- which just delegates to the [Rails
61
- implementation](https://api.rubyonrails.org/v6.0.1/classes/ActionController/Renderer.html)
62
- as you'd do in a typical rails controller. Remember that you can provide
63
- template instance variables through the keyword `:assigns`.
57
+ The main method that this extension adds to `WebPipe::Conn` is `#render`, which
58
+ delegates to the [Rails implementation]
59
+ (https://api.rubyonrails.org/v6.0.1/classes/ActionController/Renderer.html) as
60
+ you'd do in a typical rails controller. Remember that you can provide template
61
+ instance variables through the keyword `:assigns`.
64
62
 
65
63
  ```ruby
66
64
  # config/routes.rb
@@ -93,10 +91,10 @@ end
93
91
  ```
94
92
 
95
93
  Notice that we used the keyword `template:` instead of taking advantage of
96
- automatic template lookup. We did that way so that we don't have to create also
97
- an `ArticlesController`, but it's up to you. In the case of having an
98
- `ArticlesController` we could just do `conn.render(:index, assigns: {
99
- articles: Article.all })`.
94
+ automatic template lookup. We did that way so that we don't have to create an
95
+ `ArticlesController`, but it's up to you. In the case of having an
96
+ `ArticlesController`, we could do `conn.render(:index, assigns: { articles:
97
+ Article.all })`.
100
98
 
101
99
  Besides, this extension provides with two other methods:
102
100
 
@@ -105,12 +103,7 @@ Besides, this extension provides with two other methods:
105
103
  - `helpers` returns the associated [controller
106
104
  helpers](https://api.rubyonrails.org/classes/ActionController/Helpers.html).
107
105
 
108
- In all the examples we have supposed that we are putting `WebPipe` applications
109
- within `app/controllers/` directory. However, remember you can put them
110
- wherever you like as long as you respect rails [`autoload_paths`](https://guides.rubyonrails.org/autoloading_and_reloading_constants.html#autoload-paths).
111
-
112
- Here you have a link to a very simple and contrived example of a rails
113
- application integrating `web_pipe`:
114
-
115
- https://github.com/waiting-for-dev/rails-web_pipe
116
-
106
+ We have placed `WebPipe` applications within `app/controllers/` directory in
107
+ all the examples. However, remember you can put them wherever you like as long
108
+ as you respect rails
109
+ [`autoload_paths`](https://guides.rubyonrails.org/autoloading_and_reloading_constants.html#autoload-paths).
@@ -1,14 +1,15 @@
1
1
  # Redirect
2
2
 
3
- This extension helps with creating a redirect response.
3
+ This extension helps create a redirect response.
4
4
 
5
5
  Redirect responses consist of two pieces:
6
6
 
7
- - `Location` response header with the URL to which browsers should redirect.
7
+ - The `Location` response header with the URL to which browsers should
8
+ redirect.
8
9
  - A 3xx status code.
9
10
 
10
- A `#redirect(location, code)` method is added to `WebPipe::Conn` which takes
11
- care of both steps. `code` argument is optional, defaulting to `302`.
11
+ A `#redirect(location, code)` method is added to `WebPipe::Conn`, which takes
12
+ care of both steps. The `code` argument is optional, defaulting to `302`.
12
13
 
13
14
  ```ruby
14
15
  require 'web_pipe'
@@ -1,12 +1,12 @@
1
1
  # Router params
2
2
 
3
- This extension can be used in order to merge placeholder parameters
3
+ This extension can be used to merge placeholder parameters
4
4
  that usually routers support (like `get /users/:id`) to the parameters hash
5
- added through [`:params` extension](params.md) (which is
6
- automatically loaded).
5
+ added through the [`:params` extension](params.md) (which is
6
+ automatically loaded if using `:router_params`).
7
7
 
8
- What this extension does is adding a transformation function to the registry
9
- with name `:router_params`. Internally, it merges what is present in rack env's
8
+ This extension adds a transformation function named `:router_params`to the
9
+ registry. Internally, it merges what is present in rack env's
10
10
  `router.params` key.
11
11
 
12
12
  It automatically integrates with
@@ -1,11 +1,11 @@
1
1
  # Session
2
2
 
3
- Wrapper around `Rack::Session` middleware to help working with
4
- sessions in your plugged operations.
3
+ Wrapper around `Rack::Session` middleware to help work with sessions in your
4
+ plugged operations.
5
5
 
6
- It depends on `Rack::Session` middleware, which is shipped by rack.
6
+ It depends on the `Rack::Session` middleware, which is shipped by rack.
7
7
 
8
- It adds following methods to `WebPipe::Conn`:
8
+ It adds the following methods to `WebPipe::Conn`:
9
9
 
10
10
  - `#fetch_session(key)`, `#fetch_session(key, default)` or
11
11
  `#fetch_session(key) { default }`. Returns what is stored under
@@ -1,11 +1,11 @@
1
1
  # URL
2
2
 
3
- `:url` extension just adds a few methods which cook raw request information
4
- about the URL into something more digestible.
3
+ The `:url` extension adds a few methods that process the raw URL information
4
+ into something more digestable.
5
5
 
6
6
  Specifically, it adds:
7
7
 
8
- - `#base_url`: Which is schema + host + port (unless it is the default for the scheme). I.e. `'https://example.org'` or `'http://example.org:8000'`.
9
- - `#path`: Which is script name (if any) + path information. I.e. `'index.rb/users/1'` or `'users/1'`.
10
- - `#full_path`: Which is path + query string (if any). I.e. `'users/1?view=table'`.
11
- - `#url`: Which is base url + full path. I.e. `'http://example.org:8000/users/1?view=table'`.
8
+ - `#base_url`: That's schema + host + port (unless it is the default for the scheme). E.g. `'https://example.org'` or `'http://example.org:8000'`.
9
+ - `#path`: That's script name (if any) + path information. E.g. `'index.rb/users/1'` or `'users/1'`.
10
+ - `#full_path`: That's path + query string (if any). E.g. `'users/1?view=table'`.
11
+ - `#url`: That's base url + full path. E.g. `'http://example.org:8000/users/1?view=table'`.
data/docs/extensions.md CHANGED
@@ -1,12 +1,11 @@
1
1
  # Extensions
2
2
 
3
- `WebPipe::Conn` features are by default raw: the very minimal you
4
- need to be able to build a web application. However, there are
5
- several extensions to progressively add just the ingredients you
6
- want to use.
3
+ `WebPipe::Conn` features are bare-bones by default: the very minimal you need
4
+ to be able to build a web application. However, there are several extensions to
5
+ add just the ingredients you want to use progressively.
7
6
 
8
- In order to load the extensions, you have to call
9
- `#load_extensions` method in `WebPipe`:
7
+ To load the extensions, you have to call `#load_extensions` method in
8
+ `WebPipe`:
10
9
 
11
10
  ```ruby
12
11
  WebPipe.load_extensions(:params, :cookies)
data/docs/introduction.md CHANGED
@@ -6,10 +6,10 @@ It means that with it and a rack router (like
6
6
  [`hanami-router`](https://github.com/hanami/router),
7
7
  [`http_router`](https://github.com/joshbuddy/http_router) or plain
8
8
  [rack](https://github.com/rack/rack) routing methods you can build a complete
9
- web application. However, the idea behind `web_pipe` is being a decoupled
10
- component within a web framework. For this reason, it plays extremely well
11
- with [dry-rb](https://dry-rb.org/) ecosystem. If it helps, you can think of it
12
- as a decoupled web controller (as the C in MVC).
9
+ web application. However, the idea behind `web_pipe` is for it to be a
10
+ decoupled component within a web framework. For this reason, it plays
11
+ extremely well with [dry-rb](https://dry-rb.org/) ecosystem. If it helps, you
12
+ can think of it as a decoupled web controller (as the C in MVC).
13
13
 
14
14
  `web_pipe` applications are built as a [pipe of
15
15
  operations](design_model.md) on an [immutable
@@ -28,9 +28,9 @@ Following there is a simple example. It is a web application that will check
28
28
  the value of a `user` parameter. When it is `Alice` or `Joe`, it will kindly
29
29
  say hello. Otherwise, it will unauthorize:
30
30
 
31
- > In order to try this example you can paste it to a file with name `config.ru`
32
- and launch the rack command `rackup` within the same directory. The application
33
- will be available in `http://localhost:9292`.
31
+ > To try this example, you can paste it to a file with the name `config.ru` and
32
+ launch the rack command `rackup` within the same directory. The application
33
+ will be available at `http://localhost:9292`.
34
34
 
35
35
  ```ruby
36
36
  require 'web_pipe'
@@ -5,9 +5,9 @@ and returning a connection struct. As a result, a composition of operations is
5
5
  an operation in itself (as it also takes a connection struct and returns a
6
6
  connection struct).
7
7
 
8
- This can be leveraged to plug a whole `web_pipe` application as an operation
9
- to another application. Doing so, you are plugging an operation which is the
10
- composition of all operations for given application.
8
+ We can leverage that to plug a whole `web_pipe` application as an operation to
9
+ another application. By doing so, you are plugging an operation which is the
10
+ composition of all operations for a given application.
11
11
 
12
12
  ```ruby
13
13
  class HtmlApp
@@ -1,12 +1,12 @@
1
1
  # Injecting operations
2
2
 
3
- Operations can be injected at the moment an application is initialized,
4
- which allows you to override what the definition declares.
3
+ You can inject operations at the moment an application is initialized. It
4
+ allows you to override what the definition declares.
5
5
 
6
6
  To this effect, you must use `plugs:` keyword argument. It must be a hash where
7
- operations are matched by the name you gave them in its definition.
7
+ the operations are matched by the name you gave them in its definition.
8
8
 
9
- This is mainly useful for testing purposes, where you can switch a heavy
9
+ That is mainly useful for testing purposes, where you can switch a heavy
10
10
  operation and use another lighter one.
11
11
 
12
12
  In the following example, the response body of the application will be
@@ -0,0 +1,24 @@
1
+ # Inspecting operations
2
+
3
+ Once a `WebPipe` class is initialized, all its operations get resolved. It
4
+ happens because they are whether [resolved](resolving_operations.md) or
5
+ [injected](injecting_operations.md). The final result can be accessed through
6
+ the `#operations` method:
7
+
8
+ ```ruby
9
+ require 'web_pipe'
10
+ require 'web_pipe/conn_support/builder'
11
+
12
+ class MyApp
13
+ include WebPipe
14
+
15
+ plug(:hello) do |conn|
16
+ conn.set_response_body('Hello world!')
17
+ end
18
+ end
19
+
20
+ app = MyApp.new
21
+ conn = WebPipe::ConnSupport::Builder.call(Rack::MockRequest.env_for)
22
+ new_conn = app.operations[:hello].call(con)
23
+ conn.response_body #=> ['Hello world!']
24
+ ```
@@ -1,6 +1,6 @@
1
1
  # Resolving operations
2
2
 
3
- There are several ways you can specify how an operation is resolved.
3
+ There are several ways you can specify how to resolve an operation.
4
4
 
5
5
  ## Instance method
6
6
 
@@ -53,8 +53,8 @@ end
53
53
  Operations can be resolved from a dependency injection container.
54
54
 
55
55
  A container is anything that responds to `#[]` (accepting `Symbol` or `String`
56
- as argument) in order to resolve a dependency. It can be configured at the
57
- moment `WebPipe` module is included:
56
+ as argument) to resolve a dependency. It can be configured at the
57
+ moment you include the `WebPipe` module:
58
58
 
59
59
  ```ruby
60
60
  MyContainer = Hash[
@@ -1,10 +1,10 @@
1
1
  # Plugging operations
2
2
 
3
- You can plug operations to your application with the DSL method `plug`. The
3
+ You can plug operations into your application with the DSL method `plug`. The
4
4
  first argument it always takes is a symbol with the name you want
5
5
  to give to the operation (which is needed to allow
6
- [injection](plugging_operations/injecting_operations.md) on
7
- initialization).
6
+ [injection](plugging_operations/injecting_operations.md) at
7
+ initialization time).
8
8
 
9
9
  ```ruby
10
10
  class MyApp
data/docs/plugs/config.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Config
2
2
 
3
- `Config` plug helps in the addition of configuration settings (`#config` hash
3
+ The `Config` plug helps in adding configuration settings (`#config` hash
4
4
  attribute) to an instance of `WebPipe::Conn`.
5
5
 
6
6
  ```ruby
@@ -1,6 +1,7 @@
1
1
  # ContentType
2
2
 
3
- `ContentType` plug is just a helper to set `Content-Type` response header.
3
+ The `ContentType` plug is just a helper to set the `Content-Type` response
4
+ header.
4
5
 
5
6
  Example:
6
7
 
data/docs/plugs.md CHANGED
@@ -1,13 +1,12 @@
1
1
  # Plugs
2
2
 
3
- Some group of operations can be generalized as following same pattern. For
3
+ Some groups of operations can be generalized as following the same pattern. For
4
4
  example, an operation setting `Content-Type` header to `text/html` is very
5
- similar to another one setting same header to `application/json`. We name plugs
6
- to this level of abstraction on top of operations: plugs are operation
7
- builders. In other words, they are higher order functions which return
8
- functions.
5
+ similar to setting the same header to `application/json`. We name plugs to this
6
+ level of abstraction on top of operations: plugs are operation builders. In
7
+ other words, they are higher-order functions that return functions.
9
8
 
10
- Being just functions, we take as convention that plugs respond to `#call` in
11
- order to create an operation.
9
+ Being just functions, we take as a convention that plugs respond to `#call` to
10
+ create an operation.
12
11
 
13
12
  This library ships with some useful plugs.
@@ -0,0 +1,12 @@
1
+ # Hanami 2 and dry-rb integration
2
+
3
+ `web_pipe` has been designed to integrate smoothly with
4
+ the [hanami](https://hanamirb.org/) & [dry-rb](https://dry-rb.org/) ecosystems. It shares the same design
5
+ principles, and it ships with some extensions that even make this
6
+ integration painless (like [`:dry-schema`](../extensions/dry_schema.md)
7
+ extension or [`:hanami_view`](../extensions/hanami_view.md)).
8
+
9
+ If you want to use `web_pipe` within a hanami 2 application, you can take
10
+ inspiration from this sample todo app:
11
+
12
+ https://github.com/waiting-for-dev/hanami_2_web_pipe_todo_app
@@ -22,4 +22,6 @@ end
22
22
  run router
23
23
  ```
24
24
 
25
- In order to perform [string matching with variables](https://github.com/hanami/router#string-matching-with-variables) you just need to load [`:router_params` extension](../extensions/router_params.md).
25
+ To perform [string matching with
26
+ variables](https://github.com/hanami/router#string-matching-with-variables) you
27
+ just need to load [`:router_params` extension](../extensions/router_params.md).
@@ -1,6 +1,6 @@
1
1
  # Using all RESTful methods
2
2
 
3
- As you probably know, a lot of browsers don't support some RESTful
3
+ As you probably know, most browsers don't support some RESTful
4
4
  methods like `PATCH` or `PUT`. [Rack's `MethodOverride`
5
5
  middleware](https://github.com/rack/rack/blob/master/lib/rack/method_override.rb)
6
6
  provides a workaround for this limitation, allowing to override
@@ -9,12 +9,13 @@ request method in rack's env if a magical `_method` parameter or
9
9
 
10
10
  You have to be aware that if you use this middleware within a
11
11
  `web_pipe` application (through [`use` DSL
12
- method](../using_rack_middlewares.md)) it will have no effect.
13
- When your `web_pipe` application takes control of the request it
14
- has already gone through the router, which is the one who should
12
+ method](../using_rack_middlewares.md)), it will have no effect.
13
+ When your `web_pipe` application takes control of the request, it
14
+ has already gone through the router, which is the one that should
15
15
  read the request method set by rack.
16
16
 
17
- The solution for this is very simple. Just use `MethodOverride` middleware before your router does its work. For example, in `config.ru`:
17
+ The solution for this is straightforward. Just use `MethodOverride` middleware
18
+ before your router does its work. For example, in `config.ru`:
18
19
 
19
20
  ```ruby
20
21
  # config.ru
data/docs/testing.md ADDED
@@ -0,0 +1,64 @@
1
+ # Testing
2
+
3
+ ## Testing the rack application
4
+
5
+ A `WebPipe` instance is a just a rack application, so you can test it as such:
6
+
7
+ ```ruby
8
+ require 'web_pipe'
9
+ require 'rack/mock'
10
+ require 'rspec'
11
+
12
+ class MyApp
13
+ include WebPipe
14
+
15
+ plug :response
16
+
17
+ private
18
+
19
+ def response(conn)
20
+ conn
21
+ .set_response_body('Hello!')
22
+ .set_status(200)
23
+ end
24
+ end
25
+
26
+ RSpec.describe MyApp do
27
+ it 'responds with 200 status code' do
28
+ env = Rack::MockRequest.env_for
29
+
30
+ status, _headers, _body = described_class.new.call(env)
31
+
32
+ expect(status).to be(200)
33
+ end
34
+ end
35
+ ```
36
+
37
+ ## Testing individual operations
38
+
39
+ Each operation in a pipe is an isolated function that takes a connection struct
40
+ as argument. You can leverage [the inspection of
41
+ operations](docs/plugging_operations/inspecting_operations.md) to unit test them.
42
+
43
+ There's also a `WebPipe::TestSupport` module that you can include to get a
44
+ helper method `#build_conn` to easily create a connection struct.
45
+
46
+ ```ruby
47
+ RSpec.describe MyApp do
48
+ include WebPipe::TestSupport
49
+
50
+ describe '#response' do
51
+ it 'responds with 200 status code' do
52
+ conn = build_conn
53
+ operation = described_class.new.operations[:response]
54
+
55
+ new_conn = operation.call(conn)
56
+
57
+ expect(new_conn.status).to be(200)
58
+ end
59
+ end
60
+ end
61
+ ```
62
+
63
+ Check the API documentation for the options you can provide to
64
+ [`#build_conn`](https://www.rubydoc.info/github/waiting-for-dev/web_pipe/master/WebPipe/TestSupport#build_conn).
@@ -3,9 +3,8 @@
3
3
  In a similar way that you compose plugged operations, you can also compose rack
4
4
  middlewares from another application.
5
5
 
6
- For that, you just need to `use` another application. When you do so, all the
7
- middlewares for that application will be added to the stack in the same order
8
- they had there.
6
+ For that, you just need to `use` another application. All the middlewares for
7
+ that application will be added to the stack in the same order.
9
8
 
10
9
  ```ruby
11
10
  class HtmlApp