render_turbo_stream 1.4.4 → 1.4.5
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 +4 -4
- data/README.md +37 -7
- data/app/views/render_turbo_stream.html.erb +8 -2
- data/lib/render_turbo_stream/test/request_helpers.rb +52 -23
- data/lib/render_turbo_stream/test/rspec_request_helpers.rb +15 -7
- data/lib/render_turbo_stream/version.rb +1 -1
- data/lib/render_turbo_stream.rb +51 -11
- metadata +4 -4
- data/app/views/_render_turbo_stream.turbo_stream.erb +0 -49
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0c77fc6dda3c5b3edc629f63a7f572835b1e6c5c4e22cd7708eb9d5dd4be99db
|
4
|
+
data.tar.gz: 83552375772d2a578a39fbca51b0ef586b47eb4eafc9de7a949a00472f61c78a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9d6e8e06675b08dc65465da8424c918bb65757a2d8fa053ea5b6d9dc98bb452bdc152c350c08f80a762c0ab9c08d5afbdf7bf6aa3b65b4fe60a80bf4a8f197f7
|
7
|
+
data.tar.gz: ab8b0e8d42d0957e632881148b28f29e67c3380dc4e61191c54697c7a255d03b463d213bb494b780cc948be941da017d17a23b8758f6caa5d26e9b499b693ed4
|
data/README.md
CHANGED
@@ -8,6 +8,8 @@ And build it dynamically: Most [turbo_power](https://github.com/marcoroth/turbo_
|
|
8
8
|
|
9
9
|
ATTENTION: This plugin is in a early state.
|
10
10
|
|
11
|
+
Hope it helps you.
|
12
|
+
|
11
13
|
An overview of how we design a rails-7 application with turbo
|
12
14
|
is [published on dev.to](https://dev.to/chmich/rails-7-vite-wrapping-up-1pia).
|
13
15
|
|
@@ -101,7 +103,7 @@ render_turbo_stream(
|
|
101
103
|
)
|
102
104
|
```
|
103
105
|
|
104
|
-
The `stream_partial` method is
|
106
|
+
The `stream_partial` method is just for rendering a partial alone.
|
105
107
|
|
106
108
|
```ruby
|
107
109
|
stream_partial(
|
@@ -129,9 +131,6 @@ render_turbo_stream(
|
|
129
131
|
:add_css_class,
|
130
132
|
'#colored-element',
|
131
133
|
'red'
|
132
|
-
],
|
133
|
-
[
|
134
|
-
|
135
134
|
]
|
136
135
|
]
|
137
136
|
)
|
@@ -141,14 +140,34 @@ Under the hood, inside a `*.turbo_stream.erb` template, it does the following: `
|
|
141
140
|
|
142
141
|
**WORKAROUND for redirects inside frame**
|
143
142
|
|
144
|
-
|
143
|
+
Suppose you have a CRUD controller that should do all its actions inside a turbo frame. Classic redirect_to, along with a Flash message, would raise "Render and/or redirect were called multiple times in this action". See [issue] (https://gitlab.com/sedl/renderturbostream/-/issues/3).
|
144
|
+
|
145
|
+
You can handle this by reloading the parent frame's src attribute. The code might look like this:
|
146
|
+
|
147
|
+
```ruby
|
148
|
+
def update
|
149
|
+
@car = Car.find(params['id'])
|
150
|
+
turbo_stream_save(
|
151
|
+
@car.update(car_params),
|
152
|
+
streams_on_success: [
|
153
|
+
[
|
154
|
+
:turbo_frame_set_src,
|
155
|
+
'cars-box',
|
156
|
+
cars_path
|
157
|
+
]
|
158
|
+
]
|
159
|
+
)
|
160
|
+
end
|
161
|
+
|
162
|
+
```
|
145
163
|
|
146
164
|
**Parameters for turbo_stream_save**
|
147
165
|
|
148
166
|
save_action,
|
149
|
-
redirect_on_success_to: nil,
|
167
|
+
redirect_on_success_to: nil, # does a regular redirect. Works if you are inside a turbo_frame and just want to redirect inside that frame BUT CANNOT STREAM OTHERS ACTIONS ON THE SAME RESPONSE https://github.com/rails/rails/issues/48056
|
168
|
+
turbo_redirect_on_success_to: nil, # does a full page redirect (break out of all frames by turbo_power redirect)
|
150
169
|
object: nil, # object used in save_action, example: @customer
|
151
|
-
id:
|
170
|
+
id: nil, # if nil: no partial is rendered
|
152
171
|
partial: nil, # example: 'customers/form' default: "#{controller_path}/#{id}"
|
153
172
|
action: 'replace', # options: append, prepend
|
154
173
|
locals: {}, # locals used by the partial
|
@@ -255,6 +274,17 @@ For more detailed testing of partials, there are view tests.
|
|
255
274
|
Testing the plugin itself: There is a [quick-and-dirty app](https://gitlab.com/sedl/renderturbostream_railsapp) which
|
256
275
|
includes the plugin and has tests done by rspec/request and capybara.
|
257
276
|
|
277
|
+
## More Configs
|
278
|
+
|
279
|
+
On test helpers, the marker for a turbo-stream target is in most cases the id of the target element. This is true for the standard turbo-stream functions. On `turbo_power` it is the same in most cases. `RenderTurboStream::Libs.first_attr_is_html_id()` checks for which methods this is true. You can override this:
|
280
|
+
|
281
|
+
```ruby
|
282
|
+
config.x.render_turbo_stream.first_attribute_is_html_id = %[replace append prepend turbo_frame_set_src]
|
283
|
+
```
|
284
|
+
|
285
|
+
This setting is relevant for testing helpers.
|
286
|
+
|
287
|
+
|
258
288
|
## Contributing
|
259
289
|
|
260
290
|
Contribution welcome.
|
@@ -1,13 +1,19 @@
|
|
1
1
|
<% rendered_partials = [] %>
|
2
2
|
|
3
|
+
|
3
4
|
<% streams.each do |s| %>
|
4
5
|
|
5
6
|
<% if s.is_a?(Array) %>
|
6
|
-
<%
|
7
|
+
<% attr_id = RenderTurboStream::Libs.first_attr_is_html_id(s.first) %>
|
8
|
+
<% h = { attributes: s, type: 'command' } %>
|
9
|
+
<% h[:target] = "##{s.second}" if attr_id %>
|
10
|
+
<% rendered_partials.push(h) %>
|
7
11
|
<% else %>
|
8
12
|
<% html = (render s[:partial], locals: s[:locals]&.symbolize_keys, formats: [:html]) %>
|
9
13
|
<% s.delete(:partial) %>
|
10
|
-
<%
|
14
|
+
<% s[:target] = "##{s[:id]}" %>
|
15
|
+
<% s.delete(:id) %>
|
16
|
+
<% rendered_partials.push({ html_response: html, type: 'partial' }.merge(s)) %>
|
11
17
|
<% end %>
|
12
18
|
|
13
19
|
|
@@ -4,24 +4,7 @@ module RenderTurboStream
|
|
4
4
|
|
5
5
|
# log as helper for the developer to see which flash is set and which partials are rendered to wich ids
|
6
6
|
def streams_log
|
7
|
-
|
8
|
-
r = []
|
9
|
-
if response.status == 302
|
10
|
-
r.push("redirect to #{turbo_redirect_to}")
|
11
|
-
else
|
12
|
-
all_responses.map do |a|
|
13
|
-
str = [
|
14
|
-
a['action'],
|
15
|
-
'id',
|
16
|
-
"«#{a['id']}»",
|
17
|
-
'by partial',
|
18
|
-
"«#{a['partial']}»",
|
19
|
-
(a['locals'].present? ? "locals: «#{a['locals']}»" : nil)
|
20
|
-
].compact.join(' ')
|
21
|
-
r.push(str)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
r
|
7
|
+
RenderTurboStream::Libs.all_responses(response)
|
25
8
|
end
|
26
9
|
|
27
10
|
# Returns the path to which turbo_stream.redirect_to would be applied.
|
@@ -29,11 +12,13 @@ module RenderTurboStream
|
|
29
12
|
resps = RenderTurboStream::Libs.all_responses(response)
|
30
13
|
url = nil
|
31
14
|
resps.each do |r|
|
32
|
-
if r['
|
33
|
-
if
|
34
|
-
url
|
35
|
-
|
36
|
-
|
15
|
+
if r['type'] == 'command'
|
16
|
+
if r['attributes'].first == 'redirect_to'
|
17
|
+
if url
|
18
|
+
url = 'ERROR: REDIRECT CALLED MORE THAN ONCE'
|
19
|
+
else
|
20
|
+
url = r['attributes'].second
|
21
|
+
end
|
37
22
|
end
|
38
23
|
end
|
39
24
|
end
|
@@ -66,6 +51,50 @@ module RenderTurboStream
|
|
66
51
|
def stream_targets_count
|
67
52
|
stream_targets.length
|
68
53
|
end
|
54
|
+
|
55
|
+
# Returns false if a given action such as "replace" (for: turbo_stream.replace) is not performed exactly once on a given target id. Otherwise, it returns an array of attributes that were used to call the function.
|
56
|
+
# For stream actions, this only works if the given action has the HTML-ID as its first element.
|
57
|
+
def stream_action_once(action, id)
|
58
|
+
all_responses = RenderTurboStream::Libs.all_responses(response)
|
59
|
+
counts = {}
|
60
|
+
res = nil
|
61
|
+
all_responses.each do |r|
|
62
|
+
|
63
|
+
if r['type'] == 'command'
|
64
|
+
act = r['attributes'].first
|
65
|
+
is_id = RenderTurboStream::Libs.first_attr_is_html_id(act)
|
66
|
+
if action.to_s == act && is_id && r['attributes'].second == id.to_s
|
67
|
+
k = [act, r['attributes'].second].join('-')
|
68
|
+
counts[k] ||= 0
|
69
|
+
counts[k] += 1
|
70
|
+
if counts[k] == 1
|
71
|
+
res = r['attributes']
|
72
|
+
else
|
73
|
+
res = false
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
elsif r['type'] == 'partial'
|
78
|
+
|
79
|
+
act = r['action']
|
80
|
+
is_id = r['target'][0] == '#'
|
81
|
+
_id = r['target'][1..-1]
|
82
|
+
if action.to_s == act && is_id && _id == id.to_s
|
83
|
+
k = [act, _id].join('-')
|
84
|
+
counts[k] ||= 0
|
85
|
+
counts[k] += 1
|
86
|
+
if counts[k] == 1
|
87
|
+
res = [act, id, { locals: r['locals'] }]
|
88
|
+
else
|
89
|
+
res = false
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
end
|
95
|
+
res
|
96
|
+
end
|
97
|
+
|
69
98
|
end
|
70
99
|
end
|
71
100
|
end
|
@@ -2,22 +2,30 @@ module RenderTurboStream
|
|
2
2
|
module Test
|
3
3
|
module RspecRequestHelpers
|
4
4
|
|
5
|
-
|
6
5
|
# expect status 200 and a each one time response to given ids
|
7
6
|
|
8
7
|
def expect_successful_saved(*ids)
|
9
8
|
responses = RenderTurboStream::Libs.all_responses(response)
|
10
|
-
|
9
|
+
id_counts = {}
|
11
10
|
responses.each do |r|
|
12
|
-
|
13
|
-
|
11
|
+
if r['target'].is_a?(Array)
|
12
|
+
r['target'].each do |t|
|
13
|
+
id = (t[0] == '#' ? t[1..-1] : t)
|
14
|
+
id_counts[t.to_s] ||= 0
|
15
|
+
id_counts[t.to_s] += 1
|
16
|
+
end
|
17
|
+
else
|
18
|
+
id = (r['target'][0] == '#' ? r['target'][1..-1] : r['target'])
|
19
|
+
id_counts[id] ||= 0
|
20
|
+
id_counts[id] += 1
|
21
|
+
end
|
14
22
|
end
|
15
23
|
|
16
24
|
expect(response.status).to eq(200)
|
17
|
-
expect(
|
25
|
+
expect(id_counts.keys.length).to eq(ids.length)
|
18
26
|
ids.each do |id|
|
19
|
-
expect(
|
20
|
-
expect(
|
27
|
+
expect(id_counts.key?(id)).to be_truthy
|
28
|
+
expect(id_counts[id]).to eq(1)
|
21
29
|
end
|
22
30
|
end
|
23
31
|
|
data/lib/render_turbo_stream.rb
CHANGED
@@ -8,7 +8,7 @@ module RenderTurboStream
|
|
8
8
|
|
9
9
|
def turbo_stream_save(
|
10
10
|
save_action,
|
11
|
-
redirect_on_success_to: nil, # does a regular redirect. Works if you are inside a turbo_frame and just want to redirect inside that frame BUT CANNOT STREAM OTHERS ACTIONS
|
11
|
+
redirect_on_success_to: nil, # does a regular redirect. Works if you are inside a turbo_frame and just want to redirect inside that frame BUT CANNOT STREAM OTHERS ACTIONS ON THE SAME RESPONSE https://github.com/rails/rails/issues/48056
|
12
12
|
turbo_redirect_on_success_to: nil, # does a full page redirect (break out of all frames by turbo_power redirect)
|
13
13
|
object: nil, # object used in save_action, example: @customer
|
14
14
|
id: nil, # if nil: no partial is rendered
|
@@ -43,7 +43,7 @@ module RenderTurboStream
|
|
43
43
|
|
44
44
|
#== Streams / Partials
|
45
45
|
|
46
|
-
streams =
|
46
|
+
streams = (id ? [id: id, partial: partial, locals: locals, action: action] : [])
|
47
47
|
|
48
48
|
if save_action
|
49
49
|
response.status = 200
|
@@ -160,7 +160,7 @@ module RenderTurboStream
|
|
160
160
|
ary = []
|
161
161
|
array.each do |pr|
|
162
162
|
if !pr.present?
|
163
|
-
a=1
|
163
|
+
a = 1
|
164
164
|
elsif pr.is_a?(Hash)
|
165
165
|
props = pr.symbolize_keys
|
166
166
|
part = (props[:partial].present? ? props[:partial] : props[:id]).gsub('-', '_')
|
@@ -214,7 +214,7 @@ module RenderTurboStream
|
|
214
214
|
|
215
215
|
all.select do |a|
|
216
216
|
if id.present?
|
217
|
-
a['
|
217
|
+
a['target'] == "##{id}"
|
218
218
|
else
|
219
219
|
false
|
220
220
|
end
|
@@ -223,15 +223,19 @@ module RenderTurboStream
|
|
223
223
|
end
|
224
224
|
|
225
225
|
def self.stream_targets(response)
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
226
|
+
responses = all_responses(response)
|
227
|
+
targets = []
|
228
|
+
responses.each do |r|
|
229
|
+
if r['target'].is_a?(Array)
|
230
|
+
r['target'].each do |t|
|
231
|
+
targets.push(t) unless targets.include?(t)
|
232
|
+
end
|
233
|
+
else
|
234
|
+
targets.push(r['target']) unless targets.include?(r['target'])
|
232
235
|
end
|
233
236
|
end
|
234
|
-
|
237
|
+
|
238
|
+
targets
|
235
239
|
end
|
236
240
|
|
237
241
|
def self.stream_target_response_count(response, id, total, &block)
|
@@ -252,5 +256,41 @@ module RenderTurboStream
|
|
252
256
|
|
253
257
|
end
|
254
258
|
|
259
|
+
# on most methods the first attribute is the target.
|
260
|
+
# This method checks for that
|
261
|
+
# it includes the methods from turbo-power
|
262
|
+
# used for test helpers
|
263
|
+
def self.first_attr_is_html_id(method)
|
264
|
+
config = Rails.configuration.x.render_turbo_stream.first_attribute_is_html_id
|
265
|
+
default = [
|
266
|
+
:graft,
|
267
|
+
:morph,
|
268
|
+
:inner_html,
|
269
|
+
:insert_adjacent_text,
|
270
|
+
:outer_html,
|
271
|
+
:text_content,
|
272
|
+
:add_css_class,
|
273
|
+
:remove_attribute,
|
274
|
+
:remove_css_class,
|
275
|
+
:set_attribute,
|
276
|
+
:set_dataset_attribute,
|
277
|
+
:set_property,
|
278
|
+
:set_style,
|
279
|
+
:set_styles,
|
280
|
+
:set_value,
|
281
|
+
:dispatch_event,
|
282
|
+
:reset_form,
|
283
|
+
:clear_storage,
|
284
|
+
:scroll_into_view,
|
285
|
+
:set_focus,
|
286
|
+
:turbo_frame_reload,
|
287
|
+
:turbo_frame_set_src,
|
288
|
+
:replace,
|
289
|
+
:append,
|
290
|
+
:prepend
|
291
|
+
]
|
292
|
+
(config.present? ? config : default).map{|m|m.to_sym}.include?(method.to_sym)
|
293
|
+
end
|
294
|
+
|
255
295
|
end
|
256
296
|
end
|
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: 1.4.
|
4
|
+
version: 1.4.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- christian
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-04-
|
11
|
+
date: 2023-04-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -38,7 +38,6 @@ files:
|
|
38
38
|
- README.md
|
39
39
|
- Rakefile
|
40
40
|
- app/controllers/render_turbo_stream/application_controller.rb
|
41
|
-
- app/views/_render_turbo_stream.turbo_stream.erb
|
42
41
|
- app/views/render_turbo_stream.html.erb
|
43
42
|
- app/views/render_turbo_stream.turbo_stream.erb
|
44
43
|
- lib/render_turbo_stream.rb
|
@@ -73,5 +72,6 @@ requirements: []
|
|
73
72
|
rubygems_version: 3.4.12
|
74
73
|
signing_key:
|
75
74
|
specification_version: 4
|
76
|
-
summary: Render partials
|
75
|
+
summary: Render partials and execute javascript directly from the controller. With
|
76
|
+
test helpers.
|
77
77
|
test_files: []
|
@@ -1,49 +0,0 @@
|
|
1
|
-
<% error = false %>
|
2
|
-
<% control = [] %>
|
3
|
-
<% streams = local_assigns[:streams] %>
|
4
|
-
<% streams.each do |args| %>
|
5
|
-
|
6
|
-
|
7
|
-
<% if args.is_a?(Array) %>
|
8
|
-
|
9
|
-
<% ctl = "turbo_stream.#{args.first}, #{args[1..-1].join(', ')}" %>
|
10
|
-
|
11
|
-
<% if args.last.is_a?(Proc) %>
|
12
|
-
<% Rails.logger.error(" RENDER TURBO STREAM BLOCK => #{ctl}") %>
|
13
|
-
<%#= turbo_stream.replace 'form' do %>
|
14
|
-
<%#= render partial: 'articles/form' %>
|
15
|
-
<%# end %>
|
16
|
-
<%= turbo_stream.send args.first, *(args[1..-2]) { args.last.call } %>
|
17
|
-
<% else %>
|
18
|
-
<% Rails.logger.error(" RENDER TURBO POWER => #{ctl}") %>
|
19
|
-
<%= turbo_stream.send args.first, *(args[1..-1]) %>
|
20
|
-
<% end %>
|
21
|
-
|
22
|
-
<% else %>
|
23
|
-
<% ctl = { partial: args[:partial], id: args[:id], action: args[:action] } %>
|
24
|
-
<% info = { id: args[:id], partial: args[:partial], locals: args[:locals] } %>
|
25
|
-
<% if !args[:action].present? %>
|
26
|
-
<% Rails.logger.error(" ERROR RENDER TURBO STREAM => MISSING ACTION => #{args}") %>
|
27
|
-
<% error = true %>
|
28
|
-
|
29
|
-
<% elsif args[:action].present? %>
|
30
|
-
<% Rails.logger.debug(" • render-turbo-stream #{args[:action].upcase} => #{info}") %>
|
31
|
-
<%= turbo_stream.send args[:action].to_sym, args[:id] do %>
|
32
|
-
<%= render args[:partial], locals: args[:locals]&.symbolize_keys %>
|
33
|
-
<% end %>
|
34
|
-
|
35
|
-
<% else %>
|
36
|
-
<% Rails.logger.error(" ERROR RENDER TURBO STREAM => NOTHING DONE! => #{args}") %>
|
37
|
-
<% end %>
|
38
|
-
<% end %>
|
39
|
-
|
40
|
-
<% control.push(ctl) %>
|
41
|
-
|
42
|
-
<% end %>
|
43
|
-
|
44
|
-
<% if error %>
|
45
|
-
<% Rails.logger.error(" RENDER TURBO STREAM HAD ERRORS, REPEATING WHOLE ARRAY: ") %>
|
46
|
-
<% control.each do |c| %>
|
47
|
-
<% Rails.logger.error(" #{c}") %>
|
48
|
-
<% end %>
|
49
|
-
<% end %>
|