render_turbo_stream 4.3.1 → 4.3.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +53 -10
- data/app/views/render_turbo_stream.turbo_stream.erb +3 -3
- data/lib/render_turbo_stream/channel_libs.rb +1 -0
- data/lib/render_turbo_stream/controller_helpers.rb +11 -4
- data/lib/render_turbo_stream/libs.rb +25 -1
- data/lib/render_turbo_stream/test/request/helpers.rb +5 -0
- data/lib/render_turbo_stream/version.rb +1 -1
- data/lib/render_turbo_stream/view_helpers.rb +20 -0
- data/lib/render_turbo_stream.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d66f0d9cb7dc4822dbcaf38e286b855386e8637b07a922db1714b14ab63d0c6d
|
4
|
+
data.tar.gz: 017a6047f0c07a1f2847f7be92d810483c00690e1c31f0cb31581004d48f8f18
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a3853c69389798f965cb41e629fb208e6926b3a4ce2d5f0f925554cec41d470fa5963ad6d88dd1712e787be3db683f1e61cce7411c78f8dda574069f7d5a9b55
|
7
|
+
data.tar.gz: 78719ff0ab9c7299639161ba2a966786d18dc79b9f401e8112b58656f2270436c51119c3eb6297f73c4df4e40dc7843bebe4496a9a5cbcc6d187b6898fa00245
|
data/README.md
CHANGED
@@ -31,13 +31,21 @@ gem 'render_turbo_stream'
|
|
31
31
|
bundle install
|
32
32
|
```
|
33
33
|
|
34
|
+
**Include the helpers**
|
35
|
+
|
34
36
|
ApplicationController
|
35
37
|
|
36
38
|
```ruby
|
37
39
|
include RenderTurboStream::ControllerHelpers
|
38
40
|
```
|
39
41
|
|
40
|
-
|
42
|
+
Create a Initializer
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
ActionView::Base.send :include, RenderTurboStream::ViewHelpers
|
46
|
+
```
|
47
|
+
|
48
|
+
spec/rails_helper.rb (We are using rspec instead of minitest)
|
41
49
|
|
42
50
|
```ruby
|
43
51
|
RSpec.configure do |config|
|
@@ -55,6 +63,8 @@ Required Configurations for Flash Partial
|
|
55
63
|
config.x.render_turbo_stream.flash_partial = 'layouts/flash'
|
56
64
|
config.x.render_turbo_stream.flash_target_id = 'flash-box'
|
57
65
|
config.x.render_turbo_stream.flash_turbo_action = 'prepend'
|
66
|
+
|
67
|
+
# In case of redirection a flash cannot be sent by TurboStream
|
58
68
|
config.x.render_turbo_stream.allow_channel_to_me_for_turbo_stream_save = true
|
59
69
|
```
|
60
70
|
|
@@ -102,15 +112,28 @@ The Rails team has integrated `ActionCable` as `Turbo::StreamsChannel` into `Tur
|
|
102
112
|
def update
|
103
113
|
turbo_stream_save(
|
104
114
|
@article.update(article_params),
|
105
|
-
|
106
|
-
target_id: 'customer-form',
|
115
|
+
if_success_redirect_to: articles_path,
|
107
116
|
partial: 'form'
|
108
117
|
)
|
109
118
|
end
|
110
119
|
```
|
111
|
-
This will set a status, generate a flash message, and run `render_turbo_stream`. If it fails, it would result in something like this:
|
112
120
|
|
113
|
-
|
121
|
+
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:
|
122
|
+
|
123
|
+
```haml
|
124
|
+
= turbo_target_tag do
|
125
|
+
= simple_form ...
|
126
|
+
```
|
127
|
+
|
128
|
+
This will generate an element like `<turbo-target id="new-article-form">`.
|
129
|
+
|
130
|
+
And the form should work!
|
131
|
+
|
132
|
+
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.
|
133
|
+
|
134
|
+
Technical details? see later in this README.
|
135
|
+
|
136
|
+
As mentioned above, the turbo stream actions are handled by the `render_turbo_stream` controller helper:
|
114
137
|
|
115
138
|
```ruby
|
116
139
|
render_turbo_stream(
|
@@ -130,9 +153,6 @@ render_turbo_stream(
|
|
130
153
|
|
131
154
|
If the update succeeds, it will do a `redirect_to` action from turbo_power
|
132
155
|
|
133
|
-
|
134
|
-
**locals**: The hash for locals goes through a `symbolize_keys`, so you need to use locals in used partials like this: `locals[:message]`.
|
135
|
-
|
136
156
|
**More options**
|
137
157
|
|
138
158
|
`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:
|
@@ -163,7 +183,30 @@ If this config is set to true, Turbo::StreamsChannel is installed and a current
|
|
163
183
|
|
164
184
|
If an `if_success_redirect_to` argument is provided and the save action was successful, `turbo_stream_save` would send the partials by channel.
|
165
185
|
|
166
|
-
**
|
186
|
+
**Target-ID**
|
187
|
+
|
188
|
+
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`:
|
189
|
+
|
190
|
+
```ruby
|
191
|
+
# target_id(virtual_view_path, object)
|
192
|
+
target_id('customers/_form', Customer.new) #=> 'new-customer-form'
|
193
|
+
target_id('customers/_form', Customer.first) #=> 'customer-1-form'
|
194
|
+
target_id('customers/_form', nil) #=> 'customers-form'
|
195
|
+
target_id('customers/_form', 'hi-joe') #=> 'hi-joe'
|
196
|
+
```
|
197
|
+
|
198
|
+
View-helper: Assuming we are inside `customers/_my_form`:
|
199
|
+
|
200
|
+
```ruby
|
201
|
+
#=> Assuming controller-name "customers" and variable @customer is present
|
202
|
+
target_id
|
203
|
+
#=> 'customer-1-my-form'
|
204
|
+
|
205
|
+
target_id(Customer.new)
|
206
|
+
#=> 'new-customer-my-form'
|
207
|
+
```
|
208
|
+
|
209
|
+
**Target-ID: Avoid the same definition in multiple places**
|
167
210
|
|
168
211
|
Without this gem a turbo action would be wrapped within two frames, for example:
|
169
212
|
|
@@ -187,7 +230,7 @@ This means that the target id must be defined in several places: inside a partia
|
|
187
230
|
In order to avoid this kind of tedious coding, the gem has a kind of fallback built in: If the argument `partial` is given, but the attribute `target_id` is not, the gem will get the target_id from the partial. The process is:
|
188
231
|
|
189
232
|
1. Render the partial with the provided locals
|
190
|
-
2. Grabs into the partial by Nokogiri and looks for the first `
|
233
|
+
2. Grabs into the partial by Nokogiri and looks for the first `turbo-frame` or `turbo-target` element, get the id and uses this as target_id.
|
191
234
|
3. If all that not is found it raises a exception
|
192
235
|
4. wraps the partial within the `turbo_stream.*` and sends this to the front.
|
193
236
|
|
@@ -7,7 +7,6 @@
|
|
7
7
|
<% if args.is_a?(Array) %>
|
8
8
|
|
9
9
|
<% ctl = "turbo_stream.#{args.first}, #{args[1..-1].join(', ')}" %>
|
10
|
-
<% Rails.logger.debug(" • render-turbo-stream => #{ctl}") %>
|
11
10
|
<%= turbo_stream.send args.first, *(args[1..-1]) %>
|
12
11
|
|
13
12
|
|
@@ -26,7 +25,9 @@
|
|
26
25
|
|
27
26
|
<% unless args[:target].present? %>
|
28
27
|
<% args[:target] = RenderTurboStream::Libs.fetch_arguments_from_rendered_string(rendered_html)[:target] %>
|
29
|
-
<%
|
28
|
+
<% if args[:target].present? %>
|
29
|
+
<% Rails.logger.debug(" • Target #{args[:target]} found in #{args[:partial]}") %>
|
30
|
+
<% else %>
|
30
31
|
<% raise 'No target specified by arguments and no target found inside the rendered partial' %>
|
31
32
|
<% end %>
|
32
33
|
<% end %>
|
@@ -38,7 +39,6 @@
|
|
38
39
|
|
39
40
|
|
40
41
|
<% if args[:action].present? %>
|
41
|
-
<% Rails.logger.debug(" • render-turbo-stream #{args[:action].upcase} => #{info}") %>
|
42
42
|
<%= turbo_stream.send args[:action].to_sym, target_id do %>
|
43
43
|
|
44
44
|
<%= rendered_html %>
|
@@ -37,6 +37,7 @@ module RenderTurboStream
|
|
37
37
|
r = RenderTurboStream::Libs.fetch_arguments_from_rendered_string(rendered_html)
|
38
38
|
target_id = r[:target_id]
|
39
39
|
target = r[:target]
|
40
|
+
Rails.logger.debug(" • Target #{r[:target]} found in #{partial.to_s + template.to_s}")
|
40
41
|
end
|
41
42
|
end
|
42
43
|
|
@@ -12,7 +12,7 @@ module RenderTurboStream
|
|
12
12
|
if_success_redirect_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
|
13
13
|
if_success_turbo_redirect_to: nil, # does a full page redirect (break out of all frames by turbo_power redirect)
|
14
14
|
|
15
|
-
target_id: nil, # IF NIL: the gem grabs inside the rendered content for
|
15
|
+
target_id: nil, # IF NIL: the gem grabs inside the rendered content for turbo-frame tag or turbo-target (element from helper of this gem) tag and takes the id from there.
|
16
16
|
partial: nil, # if nil: the gem renders the default template by turbo-stream
|
17
17
|
action: 'replace', # options: append, prepend
|
18
18
|
locals: {},
|
@@ -79,6 +79,7 @@ module RenderTurboStream
|
|
79
79
|
response.status = 302
|
80
80
|
flash[:alert] = flashes[:alerts]
|
81
81
|
flash[:notice] = flashes[:notices]
|
82
|
+
Rails.logger.debug(" • Successful saved && Redirect by «turbo_redirect_to»")
|
82
83
|
Rails.logger.debug(" • Set flash[:alert] => #{flashes[:alerts]}") if flashes[:alerts].present?
|
83
84
|
Rails.logger.debug(" • Set flash[:notice] => #{flashes[:notices]}") if flashes[:notices].present?
|
84
85
|
render_turbo_stream([
|
@@ -91,18 +92,21 @@ module RenderTurboStream
|
|
91
92
|
elsif save_action && if_success_redirect_to.present?
|
92
93
|
response.status = 303
|
93
94
|
if allow_channel
|
94
|
-
Rails.logger.debug(" •
|
95
|
+
Rails.logger.debug(" • Send actions through Turbo::StreamsChannel")
|
95
96
|
c_libs = RenderTurboStream::ChannelLibs.new(response)
|
96
97
|
c_libs.send_actions_to_channel("authenticated-user-#{helpers.current_user.id}", streams, @render_turbo_stream_evaluate_instance_variables)
|
97
98
|
else
|
98
99
|
flash[:alert] = flashes[:alerts]
|
99
100
|
flash[:notice] = flashes[:notices]
|
101
|
+
Rails.logger.debug(" • Turbo::StreamsChannel NOT ALLOWED BY CONFIGS!")
|
100
102
|
Rails.logger.debug(" • Set flash[:alert] => #{flashes[:alerts]}") if flashes[:alerts].present?
|
101
103
|
Rails.logger.debug(" • Set flash[:notice] => #{flashes[:notices]}") if flashes[:notices].present?
|
104
|
+
Rails.logger.debug(" • Could not send #{streams.length} actions => #{streams}")
|
102
105
|
end
|
103
106
|
redirect_to if_success_redirect_to
|
104
107
|
|
105
108
|
else
|
109
|
+
Rails.logger.debug(" • Respond by TurboStream in #{streams.length} #{'action'.pluralize(streams.length)}")
|
106
110
|
streams += libs.generate_action(controller_path, target_id, action, partial, (partial ? nil : action_name), locals)
|
107
111
|
render_turbo_stream(streams)
|
108
112
|
|
@@ -114,6 +118,7 @@ module RenderTurboStream
|
|
114
118
|
|
115
119
|
ary = []
|
116
120
|
array.each do |pr|
|
121
|
+
cmd = nil
|
117
122
|
if !pr.present?
|
118
123
|
Rails.logger.warn " WARNING render_turbo_stream: Empty element inside attributes: «#{array}»"
|
119
124
|
elsif pr.is_a?(Hash)
|
@@ -133,13 +138,15 @@ module RenderTurboStream
|
|
133
138
|
end
|
134
139
|
r[:type] = 'stream-partial'
|
135
140
|
|
136
|
-
|
141
|
+
cmd = r
|
137
142
|
elsif pr.is_a?(Array)
|
138
143
|
raise "array has to contain at least one element: #{pr}" unless pr.first.present?
|
139
|
-
|
144
|
+
cmd = pr
|
140
145
|
else
|
141
146
|
raise "ERROR render_turbo_stream invalid type: Only hash or array allowed"
|
142
147
|
end
|
148
|
+
ary.push(cmd) if cmd
|
149
|
+
Rails.logger.debug(" • Stream => #{cmd}")
|
143
150
|
end
|
144
151
|
|
145
152
|
if request.format.to_sym == :turbo_stream
|
@@ -36,7 +36,7 @@ module RenderTurboStream
|
|
36
36
|
def self.fetch_arguments_from_rendered_string(rendered_string)
|
37
37
|
noko = Nokogiri::HTML(rendered_string)
|
38
38
|
frame = noko.at_css('turbo-frame')
|
39
|
-
ele = noko.at_css('
|
39
|
+
ele = noko.at_css('turbo-target')
|
40
40
|
if frame.present?
|
41
41
|
{
|
42
42
|
target_id: frame[:id],
|
@@ -52,5 +52,29 @@ module RenderTurboStream
|
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
|
+
def self.target_id(virt_view_path, id)
|
56
|
+
if id.is_a?(String)
|
57
|
+
id
|
58
|
+
elsif !id
|
59
|
+
[
|
60
|
+
virt_view_path.gsub('/', '-').gsub('-_', '-')
|
61
|
+
].join('-')
|
62
|
+
else
|
63
|
+
unless id.methods.include?(:id)
|
64
|
+
raise("target_id / argument ID: Only String or object with method :id accepted")
|
65
|
+
end
|
66
|
+
(
|
67
|
+
(
|
68
|
+
id.id ?
|
69
|
+
[id.class.to_s.downcase, id.id] :
|
70
|
+
['new', id.class.to_s.downcase]
|
71
|
+
) +
|
72
|
+
[
|
73
|
+
virt_view_path.split('/').last.sub(/^_/, '')
|
74
|
+
]
|
75
|
+
).join('-')
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
55
79
|
end
|
56
80
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module RenderTurboStream
|
2
|
+
module ViewHelpers
|
3
|
+
|
4
|
+
def turbo_target_tag(id = nil, &block)
|
5
|
+
content_tag :'turbo-target', id: target_id(id) do
|
6
|
+
if block_given?
|
7
|
+
capture(&block)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def target_id(id = nil)
|
13
|
+
libs = RenderTurboStream::Libs
|
14
|
+
virt_path = self.instance_variable_get('@current_template').instance_variable_get('@virtual_path')
|
15
|
+
obj = (id ? id : eval("@#{controller_name.singularize}"))
|
16
|
+
libs.target_id(virt_path, obj)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
data/lib/render_turbo_stream.rb
CHANGED
@@ -10,6 +10,7 @@ require 'render_turbo_stream/controller_helpers'
|
|
10
10
|
require 'render_turbo_stream/controller_channel_helpers'
|
11
11
|
|
12
12
|
require 'render_turbo_stream/channel_view_helpers'
|
13
|
+
require 'render_turbo_stream/view_helpers'
|
13
14
|
|
14
15
|
require 'render_turbo_stream/channel_libs'
|
15
16
|
require 'render_turbo_stream/controller_libs'
|
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.3
|
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-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -62,6 +62,7 @@ files:
|
|
62
62
|
- lib/render_turbo_stream/test/request/helpers.rb
|
63
63
|
- lib/render_turbo_stream/test/request/libs.rb
|
64
64
|
- lib/render_turbo_stream/version.rb
|
65
|
+
- lib/render_turbo_stream/view_helpers.rb
|
65
66
|
- lib/tasks/render_turbo_stream_tasks.rake
|
66
67
|
homepage: https://gitlab.com/sedl/renderturbostream
|
67
68
|
licenses:
|