render_turbo_stream 1.4.14 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f1923db5dbed0c8a3f0cc583ba8de9469b16f0d09fdf3d46b48002ee1099537a
|
4
|
+
data.tar.gz: 7c2bdf446e15de06c2704311fc2725b84613592ac91827eaa4df69a51d383d1a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f2258c4ae8b77734f82837a883011591a5d6798d1110f3b63cf7ea557a3a3c60e8f5a358dd9a3dc963c02e0215979d91842d25dd94dfaf6c79e8cc3cc4483e59
|
7
|
+
data.tar.gz: 1495b280772066632effbc8bf484c9d5aa867e3c8fe86d745b6264fb1e0b029420be850bfe432765ade82bc0d5617fcb1dcce2ca2a5611e4c8e01b150483f5bb
|
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
|
@@ -155,9 +170,6 @@ def update
|
|
155
170
|
:turbo_frame_set_src,
|
156
171
|
'cars-box',
|
157
172
|
cars_path
|
158
|
-
],
|
159
|
-
[
|
160
|
-
#... more actions possible ...
|
161
173
|
]
|
162
174
|
]
|
163
175
|
)
|
@@ -1,22 +1,62 @@
|
|
1
1
|
module RenderTurboStream
|
2
|
-
|
2
|
+
module TurboCableHelpers
|
3
3
|
|
4
|
+
def cable_to_all_authenticated_users
|
5
|
+
if user_signed_in?
|
4
6
|
|
5
|
-
|
7
|
+
end
|
8
|
+
end
|
6
9
|
|
10
|
+
def cable_to_me(id, action, *args, partial: nil, locals: nil)
|
11
|
+
begin
|
12
|
+
u_id = helpers.current_user&.id
|
13
|
+
a=1
|
14
|
+
unless u_id.present?
|
15
|
+
Rails.logger.debug(' • SKIP RenderTurboStream.cable_to_me because current_user is nil')
|
16
|
+
return
|
7
17
|
end
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
+
rescue
|
19
|
+
Rails.logger.debug(' • ERROR RenderTurboStream.cable_to_me because current_user is not available')
|
20
|
+
return
|
21
|
+
end
|
22
|
+
if Rails.env.test?
|
23
|
+
args = {
|
24
|
+
target: "##{id}",
|
25
|
+
action: action,
|
26
|
+
type: 'cable-partial',
|
27
|
+
args: args,
|
28
|
+
partial: partial,
|
29
|
+
locals: locals
|
30
|
+
}
|
31
|
+
h = response.headers.to_h
|
32
|
+
i = 1
|
33
|
+
loop do
|
34
|
+
k = "test-turbo-cable-#{i}"
|
35
|
+
unless h.keys.include?(k)
|
36
|
+
response.headers[k] = args.to_json
|
37
|
+
break
|
18
38
|
end
|
39
|
+
i += 1
|
19
40
|
end
|
20
|
-
|
41
|
+
end
|
42
|
+
if [:append, :prepend, :replace].include?(action.to_sym)
|
43
|
+
Turbo::StreamsChannel.send(
|
44
|
+
"broadcast_#{action}_to",
|
45
|
+
"current_user_#{helpers.current_user.id}",
|
46
|
+
*args,
|
47
|
+
target: id,
|
48
|
+
partial: partial,
|
49
|
+
locals: locals&.symbolize_keys,
|
50
|
+
layout: false
|
51
|
+
)
|
52
|
+
else
|
53
|
+
# Turbo::StreamsChannel.broadcast_action_to(
|
54
|
+
# "current_user_#{helpers.current_user.id}",
|
55
|
+
# action:'toggle_css_class',
|
56
|
+
# 'colored-element'
|
57
|
+
# )
|
58
|
+
end
|
21
59
|
end
|
60
|
+
|
61
|
+
end
|
22
62
|
end
|
@@ -1,15 +1,27 @@
|
|
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
|
12
|
+
def cable_from_all_authenticated_users
|
11
13
|
if user_signed_in?
|
12
|
-
turbo_stream_from "
|
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 local_model(object)
|
21
|
+
if (object.is_a?(String) && object[0..5] == 'gid://') || object.is_a?(GlobalID)
|
22
|
+
GlobalID::Locator.locate(object)
|
23
|
+
else
|
24
|
+
object
|
13
25
|
end
|
14
26
|
end
|
15
27
|
|
data/lib/render_turbo_stream.rb
CHANGED
@@ -16,6 +16,7 @@ module RenderTurboStream
|
|
16
16
|
id: nil, # if nil: no partial is rendered
|
17
17
|
partial: nil, # example: 'customers/form' default: "#{controller_path}/#{id}"
|
18
18
|
action: 'replace', # options: append, prepend
|
19
|
+
flash_action: action_name, # options: 'update', 'create', otherwise you have to declare a translation in config/locales like "activerecord.success.#{flash_action}" and "activerecord.errors.#{flash_action}"
|
19
20
|
locals: {}, # locals used by the partial
|
20
21
|
streams_on_success: [
|
21
22
|
{
|
@@ -67,35 +68,47 @@ module RenderTurboStream
|
|
67
68
|
if save_action
|
68
69
|
flash_notices = if flashes_on_success.present?
|
69
70
|
flashes_on_success
|
70
|
-
elsif
|
71
|
+
elsif flash_action.to_s == 'create'
|
71
72
|
str = I18n.t(
|
72
73
|
'activerecord.success.successfully_created',
|
73
74
|
default: '%<model_name>s successfully created'
|
74
75
|
)
|
75
76
|
[format(str, model_name: model_name)]
|
76
|
-
elsif
|
77
|
+
elsif flash_action.to_s == 'update'
|
77
78
|
str = I18n.t(
|
78
79
|
'activerecord.success.successfully_updated',
|
79
80
|
default: '%<model_name>s successfully updated'
|
80
81
|
)
|
81
82
|
[format(str, model_name: model_name)]
|
83
|
+
else
|
84
|
+
str = I18n.t(
|
85
|
+
"activerecord.success.#{flash_action}",
|
86
|
+
default: '%<model_name>s successfully updated'
|
87
|
+
)
|
88
|
+
[format(str, model_name: model_name)]
|
82
89
|
end
|
83
90
|
flash_alerts = []
|
84
91
|
else
|
85
92
|
flash_alerts = if flashes_on_error.present?
|
86
93
|
flashes_on_error
|
87
|
-
elsif
|
94
|
+
elsif flash_action.to_s == 'create'
|
88
95
|
str = I18n.t(
|
89
96
|
'activerecord.errors.messages.could_not_create',
|
90
97
|
default: '%<model_name>s could not be created'
|
91
98
|
)
|
92
99
|
[format(str, model_name: model_name)]
|
93
|
-
elsif
|
100
|
+
elsif flash_action.to_s == 'update'
|
94
101
|
str = I18n.t(
|
95
102
|
'activerecord.errors.messages.could_not_update',
|
96
103
|
default: '%<model_name>s could not be updated'
|
97
104
|
)
|
98
105
|
[format(str, model_name: model_name)]
|
106
|
+
else
|
107
|
+
str = I18n.t(
|
108
|
+
"activerecord.errors.messages.#{flash_action}",
|
109
|
+
default: '%<model_name>s could not be updated'
|
110
|
+
)
|
111
|
+
[format(str, model_name: model_name)]
|
99
112
|
end
|
100
113
|
flash_notices = []
|
101
114
|
end
|
@@ -145,10 +158,24 @@ module RenderTurboStream
|
|
145
158
|
])
|
146
159
|
elsif save_action && redirect_on_success_to.present?
|
147
160
|
response.status = 302
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
161
|
+
if Rails.configuration.x.render_turbo_stream.use_cable_for_turbo_stream_save && helpers.user_signed_in?
|
162
|
+
streams.each do |s|
|
163
|
+
next unless s.is_a?(Hash)
|
164
|
+
Rails.logger.debug(" • Send by Cable => «#{s}»")
|
165
|
+
cable_to_me(
|
166
|
+
s[:id],
|
167
|
+
:prepend,
|
168
|
+
partial: s[:partial],
|
169
|
+
locals: s[:locals]
|
170
|
+
)
|
171
|
+
end
|
172
|
+
|
173
|
+
else
|
174
|
+
flash[:alert] = flash_alerts
|
175
|
+
flash[:notice] = flash_notices
|
176
|
+
Rails.logger.debug(" • Set flash[:alert] => #{flash_alerts}") if flash_alerts.present?
|
177
|
+
Rails.logger.debug(" • Set flash[:notice] => #{flash_notices}") if flash_notices.present?
|
178
|
+
end
|
152
179
|
redirect_to redirect_on_success_to
|
153
180
|
|
154
181
|
else
|
@@ -184,6 +211,7 @@ module RenderTurboStream
|
|
184
211
|
if request.format.to_sym == :turbo_stream
|
185
212
|
render template: 'render_turbo_stream', locals: { streams: ary }, layout: false, formats: :turbo_stream
|
186
213
|
else
|
214
|
+
Rails.logger.debug(" • Render Turbo Stream RENDERING AS HTML because request.format => #{request.format}")
|
187
215
|
render template: 'render_turbo_stream', locals: { streams: ary }, layout: false, formats: :html
|
188
216
|
end
|
189
217
|
end
|
@@ -209,7 +237,24 @@ module RenderTurboStream
|
|
209
237
|
class Libs
|
210
238
|
def self.all_responses(response)
|
211
239
|
e = Nokogiri::HTML(response.body).search('#rendered-partials').first
|
212
|
-
|
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
|
213
258
|
end
|
214
259
|
|
215
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.0
|
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
|