render_turbo_stream 4.3.6 → 4.3.8
Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 95cbd0f9e34c5d905454c7107c682719e7f689e857ab48e94cd3a150ee475947
|
4
|
+
data.tar.gz: 2dda5f5ddcdf497c8b1c937c7bada6fb0d93b24cc7b578e6c8c7e76dafebc106
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2c95e55aed3274b6f38f272262c2d35f23f50d660cb83cb7222fc75b046819b22c219d3022e64879c858bd7bb781fddb651c3d421827f806ae5931a394430754
|
7
|
+
data.tar.gz: 23c2c473430f0c16506957f7abe7e03c119ac918b3895ed9dfa056141583831d1fa7f04523206b2cb47d44ce490c20ca974bf681cbb398511d0a91cbf31a0a28
|
data/README.md
CHANGED
@@ -105,63 +105,22 @@ The Rails team has integrated `ActionCable` as `Turbo::StreamsChannel` into `Tur
|
|
105
105
|
|
106
106
|
# Usage
|
107
107
|
|
108
|
-
|
108
|
+
**render_turbo_stream**
|
109
109
|
|
110
|
-
|
111
|
-
|
112
|
-
def create
|
113
|
-
turbo_stream_save(
|
114
|
-
@article.update(article_params),
|
115
|
-
if_success_redirect_to: articles_path,
|
116
|
-
partial: 'form'
|
117
|
-
)
|
118
|
-
end
|
119
|
-
```
|
120
|
-
|
121
|
-
Note that if you want to redirect to show path, but the save action fails, `article_path(@article)` would throw an error. For this, the arguments `if_success_turbo_redirect_to` and `if_success_redirect_to` accept procs that are evaluated only on success. So your line would look like this `if_success_redirect_to: ->{article_path(@article)}`.
|
122
|
-
|
123
|
-
Assuming we want to build a form that works within a turbo-frame, including flash messages and redirects, we have to build all that inside a `turbo-frame`, and, within that we need a target-id, that must not be a turbo-frame. For that, there is a helper:
|
124
|
-
|
125
|
-
```haml
|
126
|
-
= turbo_target_tag do
|
127
|
-
= simple_form ...
|
128
|
-
```
|
129
|
-
|
130
|
-
This will generate an element like `<turbo-target id="new-article-form">`.
|
131
|
-
|
132
|
-
And the form should work!
|
133
|
-
|
134
|
-
If the update succeeds, it sends a flash message by channel(!), because stream cannot work alongside redirect, and redirects to articles#index. If it fails, it sends a flash message by stream and replaces the form tag by stream so that the invalid fields are marked red and you can see the errors inside the form.
|
135
|
-
|
136
|
-
Technical details? see later in this README.
|
137
|
-
|
138
|
-
As mentioned above, the turbo stream actions are handled by the `render_turbo_stream` controller helper:
|
110
|
+
The basic idea for this gem is **to have all the decisions/logic within the controller** so that the views are just views. So in the end we have an array of turbo stream actions that are handled by the gem. In normal cases, `*.turbo_stream.*` templates are not needed anymore.
|
139
111
|
|
140
112
|
```ruby
|
141
113
|
render_turbo_stream(
|
142
114
|
[
|
143
115
|
{
|
144
|
-
|
145
|
-
partial: 'customers/customer_form'
|
116
|
+
partial: 'customers/customer_form' #=> The target id can be defined within the form and retrieved during rendering. The default :action is :replace
|
146
117
|
},
|
147
118
|
{
|
148
119
|
id: 'flash-wrapper',
|
149
120
|
partial: 'layouts/flashes',
|
150
|
-
action: :prepend
|
151
|
-
|
152
|
-
|
153
|
-
)
|
154
|
-
```
|
155
|
-
|
156
|
-
If the update succeeds, it will do a `redirect_to` action from turbo_power
|
157
|
-
|
158
|
-
**More options**
|
159
|
-
|
160
|
-
`render_turbo_stream` interprets a hash as a partial to be sent by `turbo_stream` and an array as a command to be sent. This allows you to perform most actions from, e.g., [turbo_power](https://github.com/marcoroth/turbo_power). An example of adding a css class to an html element and updating the browser history would look like this:
|
161
|
-
|
162
|
-
```ruby
|
163
|
-
render_turbo_stream(
|
164
|
-
[
|
121
|
+
action: :prepend,
|
122
|
+
locals: { success: true }
|
123
|
+
},
|
165
124
|
[
|
166
125
|
:push_state,
|
167
126
|
'/articles/my-special-path'
|
@@ -175,7 +134,35 @@ render_turbo_stream(
|
|
175
134
|
)
|
176
135
|
```
|
177
136
|
|
178
|
-
|
137
|
+
this enables:
|
138
|
+
|
139
|
+
- turbo-stream or custom javascript actions from turbo and all actions from [turbo_power](https://github.com/marcoroth/turbo_power)
|
140
|
+
- Testing helpers (request-testing), as mentioned later
|
141
|
+
- Helpers for handling the target id, as mentioned later
|
142
|
+
|
143
|
+
If element is an array instead of a hash, it does this under the hood: `= turbo_stream.send args.first, *(args[1..-1])`. If element is a hash, it is interpreted as a partial or template to render.
|
144
|
+
|
145
|
+
**turbo_stream_save**
|
146
|
+
|
147
|
+
`turbo_stream_save` is a special method for `update` or `create` functions with `turbo_stream`. A controller action for update might look like this:
|
148
|
+
|
149
|
+
```ruby
|
150
|
+
|
151
|
+
def create
|
152
|
+
turbo_stream_save(
|
153
|
+
@article.update(article_params),
|
154
|
+
if_success_redirect_to: articles_path,
|
155
|
+
partial: 'form'
|
156
|
+
)
|
157
|
+
end
|
158
|
+
```
|
159
|
+
- uses `render_turbo_stream` or [render_to_me](https://gitlab.com/sedl/renderturbostream/-/blob/main/README-channels.md) (if allowed by config) under the hood
|
160
|
+
- Generates translated flash messages
|
161
|
+
- Handles redirects: Either classic redirect, which would never break out of a turbo-frame or the redirect from [turbo_power](https://github.com/marcoroth/turbo_power) which does a full-page-reload.
|
162
|
+
|
163
|
+
|
164
|
+
Note that if you want to redirect to show path, but the save action fails, `article_path(@article)` would throw an error. For this, the arguments `if_success_turbo_redirect_to` and `if_success_redirect_to` accept procs that are evaluated only on success. So your line would look like this `if_success_redirect_to: ->{article_path(@article)}`.
|
165
|
+
|
179
166
|
|
180
167
|
**Config: allow_channel_to_me_for_turbo_stream_save**
|
181
168
|
|
@@ -185,6 +172,19 @@ If this config is set to true, Turbo::StreamsChannel is installed and a current
|
|
185
172
|
|
186
173
|
If an `if_success_redirect_to` argument is provided and the save action was successful, `turbo_stream_save` would send the partials by channel.
|
187
174
|
|
175
|
+
|
176
|
+
**turbo_target_tag**
|
177
|
+
|
178
|
+
Assuming we want to build a form that works within a turbo-frame, including flash messages and redirects, we have to build all that inside a `turbo-frame`, and, within that we need a target-id, that must not be a turbo-frame. For that, there is a helper:
|
179
|
+
|
180
|
+
```haml
|
181
|
+
= turbo_target_tag do
|
182
|
+
= simple_form ...
|
183
|
+
```
|
184
|
+
|
185
|
+
- Generates an element like `<turbo-target id="new-article-form">`
|
186
|
+
- If no target-id is defined on `turbo_stream_save` or `render_turbo_stream` the renderer will grab inside the rendered content for a turbo-frame or turbo-target and get the target-id from there, so you can avoid having to define the same target-id on multiple places.
|
187
|
+
|
188
188
|
**Target-ID**
|
189
189
|
|
190
190
|
The target ID for turbo has to be unique for sure, and it has to be nice, because, at least during testing the developer has to deal with it. Since the default ID builder dom_id is too simple for this, there are some helpers. How it works is best shown by the `request-test helper target_id`:
|
@@ -204,6 +204,8 @@ target_id
|
|
204
204
|
target_id(Customer.first) #=> 'customer-1-my-form'
|
205
205
|
target_id( [Customer.first, Article.last, 'hello'] ) #=> 'customer-1-article-7-hello-my-form'
|
206
206
|
target_id('hi-joe') #=> 'hi-joe'
|
207
|
+
|
208
|
+
target_id_css('hi-joe') #=> '#hi-joe'
|
207
209
|
```
|
208
210
|
|
209
211
|
Why include the filename in a html-id? Because for turbo its likely to have multiple cases for the same object on the same page, for example: _form, _show, _password. These can all be the same customer.
|
@@ -287,18 +289,6 @@ config.x.render_turbo_stream.first_argument_is_html_id = %[replace append prepen
|
|
287
289
|
|
288
290
|
This setting is relevant for testing helpers.
|
289
291
|
|
290
|
-
# Personal note
|
291
|
-
|
292
|
-
The World Wide Web, founded around 1990 by [Tim Berners-Lee](https://en.wikipedia.org/wiki/Tim_Berners-Lee), was an html response from the server.
|
293
|
-
|
294
|
-
Frameworks like Angular, Ember, React, Vue brought a much better user experience, so called "single page applications". But they changed a paradigma: Now Javascript was the processor of HTML, which is far from the [Progressive Enhancement](https://developer.mozilla.org/en-US/docs/Glossary/Progressive_Enhancement).
|
295
|
-
|
296
|
-
2021 DHH annouced a great milestone in web development with [Rails 7, "Fulfilling a Vision"](https://rubyonrails.org/2021/12/15/Rails-7-fulfilling-a-vision). The Rails core now has done a big step, for bringing a user experience like a single page app, but by reducing javascript. This is a modern back to the roots. Thank you Rails Team!
|
297
|
-
|
298
|
-
But as of 2023, I searched for months and found nothing to solve all these details to make this Vision really work for rails. Now i am really happy and i cannot imagine working without Turbo!
|
299
|
-
|
300
|
-
Let us build on this vision and make rails what it has always been: A framework ahead of its time!
|
301
|
-
|
302
292
|
# Contributing
|
303
293
|
|
304
294
|
Contributors welcome.
|
@@ -27,8 +27,8 @@
|
|
27
27
|
<% args[:target] = RenderTurboStream::Libs.fetch_arguments_from_rendered_string(rendered_html)[:target] %>
|
28
28
|
<% if args[:target].present? %>
|
29
29
|
<% Rails.logger.debug(" • Target #{args[:target]} found in #{args[:partial]}") %>
|
30
|
-
<%
|
31
|
-
<% raise "No target specified by arguments and no target found inside the rendered #{args[:partial].present? ? "partial: #{args[:partial]}" : "template: #{args[:template]}"}" %>
|
30
|
+
<% elsif rendered_html.present? %>
|
31
|
+
<% raise "No target specified by arguments and no target found inside the rendered #{args[:partial].present? ? "partial: #{args[:partial]}" : "template: #{args[:template]}"}: «#{rendered_html}»" %>
|
32
32
|
<% end %>
|
33
33
|
<% end %>
|
34
34
|
|
@@ -22,8 +22,8 @@
|
|
22
22
|
|
23
23
|
<% unless s[:target].present? %>
|
24
24
|
<% s[:target] = RenderTurboStream::Libs.fetch_arguments_from_rendered_string(html)[:target] %>
|
25
|
-
<%
|
26
|
-
<% raise "No target specified by arguments and no target found inside the rendered #{s[:partial].present? ? "partial: #{s[:partial]}" : "template: #{s[:template]}"}" %>
|
25
|
+
<% if !s[:target].present? && html.present? %>
|
26
|
+
<% raise "No target specified by arguments and no target found inside the rendered #{s[:partial].present? ? "partial: #{s[:partial]}" : "template: #{s[:template]}"}: «#{html}»" %>
|
27
27
|
<% end %>
|
28
28
|
<% end %>
|
29
29
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: render_turbo_stream
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.3.
|
4
|
+
version: 4.3.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- christian
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-06-
|
11
|
+
date: 2023-06-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|