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.
- checksums.yaml +4 -4
- data/.rubocop.yml +4 -1
- data/CHANGELOG.md +29 -0
- data/Gemfile +2 -2
- data/README.md +18 -11
- data/docs/building_a_rack_application.md +1 -1
- data/docs/composing_applications.md +4 -4
- data/docs/connection_struct/configuring_the_connection_struct.md +4 -4
- data/docs/connection_struct/halting_the_pipe.md +17 -19
- data/docs/connection_struct/sharing_data_downstream.md +9 -8
- data/docs/connection_struct.md +22 -19
- data/docs/design_model.md +10 -9
- data/docs/dsl_free_usage.md +85 -14
- data/docs/extensions/container.md +9 -10
- data/docs/extensions/cookies.md +4 -2
- data/docs/extensions/dry_schema.md +5 -4
- data/docs/extensions/flash.md +9 -11
- data/docs/extensions/{dry_view.md → hanami_view.md} +20 -22
- data/docs/extensions/not_found.md +40 -0
- data/docs/extensions/params.md +6 -4
- data/docs/extensions/rails.md +31 -38
- data/docs/extensions/redirect.md +5 -4
- data/docs/extensions/router_params.md +5 -5
- data/docs/extensions/session.md +4 -4
- data/docs/extensions/url.md +6 -6
- data/docs/extensions.md +5 -6
- data/docs/introduction.md +7 -7
- data/docs/plugging_operations/composing_operations.md +3 -3
- data/docs/plugging_operations/injecting_operations.md +4 -4
- data/docs/plugging_operations/inspecting_operations.md +24 -0
- data/docs/plugging_operations/resolving_operations.md +3 -3
- data/docs/plugging_operations.md +3 -3
- data/docs/plugs/config.md +1 -1
- data/docs/plugs/content_type.md +2 -1
- data/docs/plugs.md +6 -7
- data/docs/recipes/hanami_2_and_dry_rb_integration.md +12 -0
- data/docs/recipes/hanami_router_integration.md +3 -1
- data/docs/recipes/using_all_restful_methods.md +6 -5
- data/docs/testing.md +64 -0
- data/docs/using_rack_middlewares/composing_middlewares.md +2 -3
- data/docs/using_rack_middlewares/injecting_middlewares.md +6 -6
- data/docs/using_rack_middlewares/inspecting_middlewares.md +35 -0
- data/docs/using_rack_middlewares.md +6 -6
- data/lib/web_pipe/app.rb +22 -25
- data/lib/web_pipe/conn.rb +0 -1
- data/lib/web_pipe/conn_support/builder.rb +0 -7
- data/lib/web_pipe/conn_support/composition.rb +3 -26
- data/lib/web_pipe/conn_support/errors.rb +5 -5
- data/lib/web_pipe/conn_support/headers.rb +1 -50
- data/lib/web_pipe/conn_support/types.rb +3 -3
- data/lib/web_pipe/dsl/builder.rb +10 -19
- data/lib/web_pipe/dsl/class_context.rb +15 -40
- data/lib/web_pipe/dsl/instance_context.rb +53 -0
- data/lib/web_pipe/extensions/container/container.rb +2 -15
- data/lib/web_pipe/extensions/cookies/cookies.rb +2 -31
- data/lib/web_pipe/extensions/dry_schema/dry_schema.rb +2 -56
- data/lib/web_pipe/extensions/flash/flash.rb +2 -32
- data/lib/web_pipe/extensions/hanami_view/hanami_view.rb +67 -0
- data/lib/web_pipe/extensions/not_found/not_found.rb +26 -0
- data/lib/web_pipe/extensions/params/params.rb +2 -63
- data/lib/web_pipe/extensions/rails/rails.rb +2 -123
- data/lib/web_pipe/extensions/redirect/redirect.rb +2 -20
- data/lib/web_pipe/extensions/router_params/router_params.rb +1 -39
- data/lib/web_pipe/extensions/session/session.rb +2 -25
- data/lib/web_pipe/extensions/url/url.rb +2 -5
- data/lib/web_pipe/pipe.rb +229 -0
- data/lib/web_pipe/plug.rb +31 -65
- data/lib/web_pipe/plugs/config.rb +0 -2
- data/lib/web_pipe/plugs/content_type.rb +0 -2
- data/lib/web_pipe/rack_support/app_with_middlewares.rb +3 -26
- data/lib/web_pipe/rack_support/middleware.rb +2 -2
- data/lib/web_pipe/rack_support/middleware_specification.rb +19 -48
- data/lib/web_pipe/test_support.rb +28 -0
- data/lib/web_pipe/types.rb +1 -3
- data/lib/web_pipe/version.rb +1 -1
- data/lib/web_pipe.rb +77 -17
- data/web_pipe.gemspec +1 -2
- metadata +16 -9
- data/docs/recipes/dry_rb_integration.md +0 -18
- data/lib/web_pipe/dsl/dsl_context.rb +0 -85
- data/lib/web_pipe/dsl/instance_methods.rb +0 -114
- data/lib/web_pipe/extensions/dry_view/dry_view.rb +0 -158
@@ -1,21 +1,23 @@
|
|
1
|
-
#
|
1
|
+
# Hanami View
|
2
2
|
|
3
|
-
This
|
4
|
-
|
5
|
-
|
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
|
-
|
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 '
|
15
|
+
require 'hanami/view'
|
14
16
|
require 'my_context'
|
15
17
|
|
16
|
-
WebPipe.load_extensions(:
|
18
|
+
WebPipe.load_extensions(:hanami_view)
|
17
19
|
|
18
|
-
class SayHelloView <
|
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
|
-
|
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 '
|
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(:
|
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 `
|
65
|
-
(`
|
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
|
-
|
70
|
-
request specific data) to your
|
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 '
|
72
|
+
require 'hanami/view/context'
|
75
73
|
require 'my_import'
|
76
74
|
|
77
|
-
class MyContext <
|
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
|
+
```
|
data/docs/extensions/params.md
CHANGED
@@ -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
|
5
|
-
|
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`
|
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
|
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
|
# ...
|
data/docs/extensions/rails.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# Rails
|
2
2
|
|
3
|
-
The first two things to keep in mind
|
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).
|
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
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
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,
|
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
|
34
|
-
[`
|
35
|
-
|
36
|
-
|
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
|
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
|
46
|
-
rendering process
|
47
|
-
|
48
|
-
|
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
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
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
|
97
|
-
|
98
|
-
`ArticlesController
|
99
|
-
|
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
|
-
|
109
|
-
|
110
|
-
|
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).
|
data/docs/extensions/redirect.md
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
# Redirect
|
2
2
|
|
3
|
-
This extension helps
|
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
|
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
|
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
|
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
|
-
|
9
|
-
|
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
|
data/docs/extensions/session.md
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
# Session
|
2
2
|
|
3
|
-
Wrapper around `Rack::Session` middleware to help
|
4
|
-
|
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
|
data/docs/extensions/url.md
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
# URL
|
2
2
|
|
3
|
-
`:url` extension
|
4
|
-
|
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`:
|
9
|
-
- `#path`:
|
10
|
-
- `#full_path`:
|
11
|
-
- `#url`:
|
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
|
4
|
-
|
5
|
-
|
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
|
-
|
9
|
-
|
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
|
10
|
-
component within a web framework. For this reason, it plays
|
11
|
-
with [dry-rb](https://dry-rb.org/) ecosystem. If it helps, you
|
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
|
-
>
|
32
|
-
|
33
|
-
will be available
|
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
|
-
|
9
|
-
|
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
|
-
|
4
|
-
|
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
|
-
|
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
|
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)
|
57
|
-
moment `WebPipe` module
|
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[
|
data/docs/plugging_operations.md
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# Plugging operations
|
2
2
|
|
3
|
-
You can plug operations
|
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)
|
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
data/docs/plugs/content_type.md
CHANGED
data/docs/plugs.md
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
# Plugs
|
2
2
|
|
3
|
-
Some
|
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
|
6
|
-
|
7
|
-
|
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`
|
11
|
-
|
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
|
-
|
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,
|
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
|
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
|
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.
|
7
|
-
|
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
|