render_turbo_stream 1.4.15 → 2.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +20 -16
- data/lib/render_turbo_stream/turbo_cable_helpers.rb +48 -29
- data/lib/render_turbo_stream/turbo_cable_view_helpers.rb +20 -4
- data/lib/render_turbo_stream/version.rb +1 -1
- data/lib/render_turbo_stream.rb +23 -5
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 00fd3b24190028352872dce17416ff89c2c31a416ae8f7a349de68193f39d10c
|
4
|
+
data.tar.gz: a1e51c47081672b873a5883fe580b31144aacdd3a33835dfd5e4d19db27e950e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 837d310de30b519f668e171f6eed9fac087e7fba358b6583e7e38ec5f0b9494ed613b94c1ca346dd25b5da1bc45acc635a11b5bc9b6c9df9275f0c434c448607
|
7
|
+
data.tar.gz: 1aaa0b80f38260fc542d3e6ea584473661664a84853cdfc8ab2f09946e0ffff34bf643a7677475d72be1334720f641143e591c0e41c6b6c47d435dae1b2a35ed
|
data/README.md
CHANGED
@@ -2,17 +2,21 @@
|
|
2
2
|
|
3
3
|
Defining templates like `(create|update).turbo_stream.haml` annoyed me.
|
4
4
|
|
5
|
-
|
5
|
+
The biggest advantage of this gem is the testing strategy.
|
6
|
+
|
7
|
+
Working consistently with turbo_stream means shooting lots of partials from the backend to the frontend. This always requires the same attributes: the path to the partial, the html-id that turbo_stream points to, and maybe some locals. This gem serialises that: Partials can be controlled directly from the controller. It sets the status, generates a flash message, handles redirection, pushes it all to the front. Includes helpers for enabling request tests.
|
6
8
|
|
7
9
|
And build it dynamically: Most [turbo_power](https://github.com/marcoroth/turbo_power) commands, such as adding a css class to an html element or pushing a state to the browser history, work directly from the controller. Since turbo allows it, custom javascript functions are also possible.
|
8
10
|
|
9
11
|
ATTENTION: This plugin is in a early state.
|
10
12
|
|
11
|
-
Hope this gem can help you.
|
12
|
-
|
13
13
|
An overview of how we design a rails-7 application with turbo
|
14
14
|
is [published on dev.to](https://dev.to/chmich/rails-7-vite-wrapping-up-1pia).
|
15
15
|
|
16
|
+
A quick and dirty application with all the features, including tests, built in is [here](https://gitlab.com/sedl/renderturbostream_railsapp).
|
17
|
+
|
18
|
+
Hope it can help you.
|
19
|
+
|
16
20
|
## Installation
|
17
21
|
|
18
22
|
```ruby
|
@@ -71,6 +75,9 @@ To get redirection and many other options working, you need to follow the instal
|
|
71
75
|
|
72
76
|
A comprehensive tutorial on turbo and how to check that it is working properly can be found at [hotrails.dev](https://www.hotrails.dev/turbo-rails).
|
73
77
|
|
78
|
+
**Turbo::StreamsChannel**
|
79
|
+
|
80
|
+
The Rails team has seamlessly integrated `ActionCable` as `Turbo::StreamsChannel` into `Turbo Rails`. For installation along with this gem, see the [README](https://gitlab.com/sedl/renderturbostream/-/blob/main/README-cable.md).
|
74
81
|
## Usage
|
75
82
|
|
76
83
|
`turbo_stream_save` is a special method for streamlining `update` or `create` functions with `turbo_stream`. A controller action for update might look like this:
|
@@ -140,11 +147,19 @@ render_turbo_stream(
|
|
140
147
|
|
141
148
|
Under the hood, inside a `*.turbo_stream.erb` template, it does the following: `= turbo_stream.send args.first, *(args[1..-1])`
|
142
149
|
|
143
|
-
**
|
150
|
+
**WORKAROUNDS for redirects inside frame**
|
144
151
|
|
145
152
|
Suppose you have a CRUD controller that should do all its actions inside a turbo frame. Classic redirect_to, together with a turbo_stream action on the same response, would raise «Render and/or redirect were called multiple times in this action». See [issue](https://gitlab.com/sedl/renderturbostream/-/issues/3).
|
146
153
|
|
147
|
-
|
154
|
+
There are two workarounds:
|
155
|
+
|
156
|
+
```ruby
|
157
|
+
config.x.render_turbo_stream.use_cable_for_turbo_stream_save = true
|
158
|
+
```
|
159
|
+
|
160
|
+
With this config, the `turbo_stream_save` method will send flash messages through `Turbo::StreamsChannel` (if installed as described above) to a channel to the currently logged in user in parallel with the redirect.
|
161
|
+
|
162
|
+
Another workaround is to use the src attribute of the parent frame. `turbo_frame_set_src` comes from turbo_power. The code might look like this:
|
148
163
|
|
149
164
|
```ruby
|
150
165
|
def update
|
@@ -162,17 +177,6 @@ def update
|
|
162
177
|
|
163
178
|
```
|
164
179
|
|
165
|
-
**Turbo::StreamsChannel**
|
166
|
-
|
167
|
-
Another workaround as described above, but with more advantages, is to use Turbo Streams, which are seamlessly integrated into `turbo rails`. See the [README](https://gitlab.com/sedl/renderturbostream/-/blob/main/README-cable.md).
|
168
|
-
If setup well and configured by
|
169
|
-
|
170
|
-
```ruby
|
171
|
-
config.x.render_turbo_stream.use_cable = true
|
172
|
-
```
|
173
|
-
|
174
|
-
The `turbo_stream_save` method, in the case of classical redirects (by redirect_to), would send the flashes plus additional partials, declared on arguments by `Turbo::StreamsChannel` in parallel to the redirect.
|
175
|
-
|
176
180
|
**Parameters for turbo_stream_save**
|
177
181
|
|
178
182
|
save_action,
|
@@ -1,50 +1,69 @@
|
|
1
1
|
module RenderTurboStream
|
2
2
|
module TurboCableHelpers
|
3
3
|
|
4
|
-
def
|
5
|
-
|
4
|
+
# def cable_partial_to_all_authenticated_users
|
5
|
+
# raise "Function cable_partial_to_all_authenticated_users is "
|
6
|
+
# if user_signed_in?
|
7
|
+
#
|
8
|
+
# end
|
9
|
+
# end
|
6
10
|
|
7
|
-
|
8
|
-
|
11
|
+
def cable_partial_to_channel(action, channel, partial, id, locals: nil)
|
12
|
+
|
13
|
+
# add headers for test
|
9
14
|
|
10
|
-
def turbo_cable_to_current_user(target, action, *args, partial: nil, locals: nil)
|
11
15
|
if Rails.env.test?
|
12
16
|
args = {
|
13
|
-
target:
|
17
|
+
target: "##{id}",
|
14
18
|
action: action,
|
15
|
-
type: '
|
16
|
-
args: args,
|
19
|
+
type: 'cable-partial',
|
17
20
|
partial: partial,
|
18
21
|
locals: locals
|
19
22
|
}
|
20
23
|
h = response.headers.to_h
|
21
24
|
i = 1
|
22
25
|
loop do
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
26
|
+
k = "test-turbo-cable-#{i}"
|
27
|
+
unless h.keys.include?(k)
|
28
|
+
response.headers[k] = args.to_json
|
29
|
+
break
|
30
|
+
end
|
28
31
|
i += 1
|
29
32
|
end
|
30
33
|
end
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
34
|
+
|
35
|
+
# send
|
36
|
+
|
37
|
+
Turbo::StreamsChannel.send(
|
38
|
+
"broadcast_#{action}_to",
|
39
|
+
channel.to_s,
|
40
|
+
target: id,
|
41
|
+
partial: partial,
|
42
|
+
locals: locals&.symbolize_keys,
|
43
|
+
layout: false
|
44
|
+
)
|
45
|
+
end
|
46
|
+
|
47
|
+
def cable_partial_to_me(partial, id, action: :replace, locals: nil)
|
48
|
+
begin
|
49
|
+
u_id = helpers.current_user&.id
|
50
|
+
a=1
|
51
|
+
unless u_id.present?
|
52
|
+
Rails.logger.debug(' • SKIP RenderTurboStream.cable_partial_to_me because current_user is nil')
|
53
|
+
return
|
54
|
+
end
|
55
|
+
rescue
|
56
|
+
Rails.logger.debug(' • ERROR RenderTurboStream.cable_partial_to_me because current_user is not available')
|
57
|
+
return
|
47
58
|
end
|
59
|
+
|
60
|
+
cable_partial_to_channel(
|
61
|
+
action,
|
62
|
+
"current_user_#{helpers.current_user.id}",
|
63
|
+
partial,
|
64
|
+
id,
|
65
|
+
locals: locals
|
66
|
+
)
|
48
67
|
end
|
49
68
|
|
50
69
|
end
|
@@ -1,15 +1,31 @@
|
|
1
1
|
module RenderTurboStream
|
2
2
|
module TurboCableViewHelpers
|
3
3
|
|
4
|
-
def
|
4
|
+
def cable_from_me
|
5
5
|
if current_user
|
6
6
|
turbo_stream_from "current_user_#{current_user.id}"
|
7
|
+
else
|
8
|
+
Rails.logger.debug(" • SKIP CABLE_FROM_ME because not authenticated")
|
7
9
|
end
|
8
10
|
end
|
9
11
|
|
10
|
-
def
|
11
|
-
|
12
|
-
|
12
|
+
# def cable_from_all_authenticated_users
|
13
|
+
# if user_signed_in?
|
14
|
+
# turbo_stream_from "all_authenticated_users"
|
15
|
+
# else
|
16
|
+
# Rails.logger.debug(" • SKIP CABLE_FROM_ALL_AUTHENTICATED_USERS because not authenticated")
|
17
|
+
# end
|
18
|
+
# end
|
19
|
+
|
20
|
+
def cable_from_all
|
21
|
+
turbo_stream_from "all"
|
22
|
+
end
|
23
|
+
|
24
|
+
def local_model(object)
|
25
|
+
if (object.is_a?(String) && object[0..5] == 'gid://') || object.is_a?(GlobalID)
|
26
|
+
GlobalID::Locator.locate(object)
|
27
|
+
else
|
28
|
+
object
|
13
29
|
end
|
14
30
|
end
|
15
31
|
|
data/lib/render_turbo_stream.rb
CHANGED
@@ -158,14 +158,14 @@ module RenderTurboStream
|
|
158
158
|
])
|
159
159
|
elsif save_action && redirect_on_success_to.present?
|
160
160
|
response.status = 302
|
161
|
-
if Rails.configuration.x.render_turbo_stream.
|
161
|
+
if Rails.configuration.x.render_turbo_stream.use_cable_for_turbo_stream_save && helpers.user_signed_in?
|
162
162
|
streams.each do |s|
|
163
163
|
next unless s.is_a?(Hash)
|
164
164
|
Rails.logger.debug(" • Send by Cable => «#{s}»")
|
165
|
-
|
165
|
+
cable_partial_to_me(
|
166
|
+
s[:partial],
|
166
167
|
s[:id],
|
167
|
-
:
|
168
|
-
partial: s[:partial],
|
168
|
+
action: flash_action,
|
169
169
|
locals: s[:locals]
|
170
170
|
)
|
171
171
|
end
|
@@ -211,6 +211,7 @@ module RenderTurboStream
|
|
211
211
|
if request.format.to_sym == :turbo_stream
|
212
212
|
render template: 'render_turbo_stream', locals: { streams: ary }, layout: false, formats: :turbo_stream
|
213
213
|
else
|
214
|
+
Rails.logger.debug(" • Render Turbo Stream RENDERING AS HTML because request.format => #{request.format}")
|
214
215
|
render template: 'render_turbo_stream', locals: { streams: ary }, layout: false, formats: :html
|
215
216
|
end
|
216
217
|
end
|
@@ -236,7 +237,24 @@ module RenderTurboStream
|
|
236
237
|
class Libs
|
237
238
|
def self.all_responses(response)
|
238
239
|
e = Nokogiri::HTML(response.body).search('#rendered-partials').first
|
239
|
-
|
240
|
+
if e.present?
|
241
|
+
res = JSON.parse(e.inner_html)
|
242
|
+
else
|
243
|
+
res = []
|
244
|
+
end
|
245
|
+
cables = response.headers.to_h.select { |k| k.match(/^test-turbo-cable-[\d]+$/) }
|
246
|
+
cables.each do |k, v|
|
247
|
+
args = JSON.parse(v)
|
248
|
+
html = ApplicationController.render(partial: args['partial'], locals: args['locals'].symbolize_keys)
|
249
|
+
res.push(
|
250
|
+
args.merge(
|
251
|
+
{
|
252
|
+
'html_response' => html,
|
253
|
+
}
|
254
|
+
)
|
255
|
+
)
|
256
|
+
end
|
257
|
+
res
|
240
258
|
end
|
241
259
|
|
242
260
|
# if partial is one word, its checked against the last behind the slash, example: 'articles/form' matches 'form'
|
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
|
+
version: 2.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- christian
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-05-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|