turbo-rails 0.5.9 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +8 -11
- data/Rakefile +4 -0
- data/app/assets/javascripts/turbo.js +1427 -1112
- data/app/channels/turbo/streams/broadcasts.rb +24 -0
- data/app/helpers/turbo/frames_helper.rb +4 -0
- data/app/helpers/turbo/streams/action_helper.rb +12 -3
- data/app/helpers/turbo/streams_helper.rb +5 -3
- data/app/javascript/turbo/cable.js +6 -3
- data/app/jobs/turbo/streams/action_broadcast_job.rb +2 -0
- data/app/jobs/turbo/streams/broadcast_job.rb +2 -0
- data/app/models/concerns/turbo/broadcastable.rb +72 -9
- data/app/models/turbo/streams/tag_builder.rb +140 -11
- data/lib/install/turbo_with_asset_pipeline.rb +10 -10
- data/lib/install/turbo_with_webpacker.rb +14 -8
- data/lib/turbo/engine.rb +5 -1
- data/lib/turbo/test_assertions.rb +2 -3
- data/lib/turbo/version.rb +1 -1
- metadata +7 -7
@@ -13,6 +13,18 @@ module Turbo::Streams::Broadcasts
|
|
13
13
|
broadcast_action_to *streamables, action: :replace, target: target, **rendering
|
14
14
|
end
|
15
15
|
|
16
|
+
def broadcast_update_to(*streamables, target:, **rendering)
|
17
|
+
broadcast_action_to *streamables, action: :update, target: target, **rendering
|
18
|
+
end
|
19
|
+
|
20
|
+
def broadcast_before_to(*streamables, target:, **rendering)
|
21
|
+
broadcast_action_to *streamables, action: :before, target: target, **rendering
|
22
|
+
end
|
23
|
+
|
24
|
+
def broadcast_after_to(*streamables, target:, **rendering)
|
25
|
+
broadcast_action_to *streamables, action: :after, target: target, **rendering
|
26
|
+
end
|
27
|
+
|
16
28
|
def broadcast_append_to(*streamables, target:, **rendering)
|
17
29
|
broadcast_action_to *streamables, action: :append, target: target, **rendering
|
18
30
|
end
|
@@ -32,6 +44,18 @@ module Turbo::Streams::Broadcasts
|
|
32
44
|
broadcast_action_later_to *streamables, action: :replace, target: target, **rendering
|
33
45
|
end
|
34
46
|
|
47
|
+
def broadcast_update_later_to(*streamables, target:, **rendering)
|
48
|
+
broadcast_action_later_to *streamables, action: :update, target: target, **rendering
|
49
|
+
end
|
50
|
+
|
51
|
+
def broadcast_before_later_to(*streamables, target:, **rendering)
|
52
|
+
broadcast_action_later_to *streamables, action: :before, target: target, **rendering
|
53
|
+
end
|
54
|
+
|
55
|
+
def broadcast_after_later_to(*streamables, target:, **rendering)
|
56
|
+
broadcast_action_later_to *streamables, action: :after, target: target, **rendering
|
57
|
+
end
|
58
|
+
|
35
59
|
def broadcast_append_later_to(*streamables, target:, **rendering)
|
36
60
|
broadcast_action_later_to *streamables, action: :append, target: target, **rendering
|
37
61
|
end
|
@@ -16,12 +16,16 @@ module Turbo::FramesHelper
|
|
16
16
|
# <%= turbo_frame_tag "tray", target: "other_tray" %>
|
17
17
|
# # => <turbo-frame id="tray" target="other_tray"></turbo-frame>
|
18
18
|
#
|
19
|
+
# <%= turbo_frame_tag "tray", src: tray_path(tray), loading: "lazy" %>
|
20
|
+
# # => <turbo-frame id="tray" src="http://example.com/trays/1" loading="lazy"></turbo-frame>
|
21
|
+
#
|
19
22
|
# <%= turbo_frame_tag "tray" do %>
|
20
23
|
# <div>My tray frame!</div>
|
21
24
|
# <% end %>
|
22
25
|
# # => <turbo-frame id="tray"><div>My tray frame!</div></turbo-frame>
|
23
26
|
def turbo_frame_tag(id, src: nil, target: nil, **attributes, &block)
|
24
27
|
id = id.respond_to?(:to_key) ? dom_id(id) : id
|
28
|
+
src = url_for(src) if src.present?
|
25
29
|
|
26
30
|
tag.turbo_frame(**attributes.merge(id: id, src: src, target: target).compact, &block)
|
27
31
|
end
|
@@ -6,11 +6,20 @@ module Turbo::Streams::ActionHelper
|
|
6
6
|
#
|
7
7
|
# turbo_stream_action_tag "replace", target: "message_1", template: %(<div id="message_1">Hello!</div>)
|
8
8
|
# # => <turbo-stream action="replace" target="message_1"><template><div id="message_1">Hello!</div></template></turbo-stream>
|
9
|
-
|
10
|
-
|
9
|
+
#
|
10
|
+
# turbo_stream_action_tag "replace", targets: "message_1", template: %(<div id="message_1">Hello!</div>)
|
11
|
+
# # => <turbo-stream action="replace" targets="message_1"><template><div id="message_1">Hello!</div></template></turbo-stream>
|
12
|
+
def turbo_stream_action_tag(action, target: nil, targets: nil, template: nil)
|
11
13
|
template = action.to_sym == :remove ? "" : "<template>#{template}</template>"
|
12
14
|
|
13
|
-
|
15
|
+
if target
|
16
|
+
target = convert_to_turbo_stream_dom_id(target)
|
17
|
+
%(<turbo-stream action="#{action}" target="#{target}">#{template}</turbo-stream>).html_safe
|
18
|
+
elsif targets
|
19
|
+
%(<turbo-stream action="#{action}" targets="#{targets}">#{template}</turbo-stream>).html_safe
|
20
|
+
else
|
21
|
+
raise ArgumentError, "target or targets must be supplied"
|
22
|
+
end
|
14
23
|
end
|
15
24
|
|
16
25
|
private
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Turbo::StreamsHelper
|
2
|
-
# Returns a new <tt>Turbo::Streams::TagBuilder</tt> object that accepts stream actions and renders them
|
2
|
+
# Returns a new <tt>Turbo::Streams::TagBuilder</tt> object that accepts stream actions and renders them as
|
3
3
|
# the template tags needed to send across the wire. This object is automatically yielded to turbo_stream.erb templates.
|
4
4
|
#
|
5
5
|
# When responding to HTTP requests, controllers can declare `turbo_stream` format response templates in that same
|
@@ -39,7 +39,9 @@ module Turbo::StreamsHelper
|
|
39
39
|
# The example above will process all turbo streams sent to a stream name like <tt>account:5:entries</tt>
|
40
40
|
# (when Current.account.id = 5). Updates to this stream can be sent like
|
41
41
|
# <tt>entry.broadcast_append_to entry.account, :entries, target: "entries"</tt>.
|
42
|
-
def turbo_stream_from(*streamables)
|
43
|
-
|
42
|
+
def turbo_stream_from(*streamables, **attributes)
|
43
|
+
attributes[:channel] = "Turbo::StreamsChannel"
|
44
|
+
attributes[:"signed-stream-name"] = Turbo::StreamsChannel.signed_stream_name(streamables)
|
45
|
+
tag.turbo_cable_stream_source(**attributes)
|
44
46
|
end
|
45
47
|
end
|
@@ -1,15 +1,18 @@
|
|
1
1
|
let consumer
|
2
2
|
|
3
3
|
export async function getConsumer() {
|
4
|
-
|
5
|
-
const { createConsumer } = await import("@rails/actioncable/src")
|
6
|
-
return setConsumer(createConsumer())
|
4
|
+
return consumer || setConsumer(createConsumer().then(setConsumer))
|
7
5
|
}
|
8
6
|
|
9
7
|
export function setConsumer(newConsumer) {
|
10
8
|
return consumer = newConsumer
|
11
9
|
}
|
12
10
|
|
11
|
+
export async function createConsumer() {
|
12
|
+
const { createConsumer } = await import(/* webpackChunkName: "actioncable" */ "@rails/actioncable/src")
|
13
|
+
return createConsumer()
|
14
|
+
}
|
15
|
+
|
13
16
|
export async function subscribeTo(channel, mixin) {
|
14
17
|
const { subscriptions } = await getConsumer()
|
15
18
|
return subscriptions.create(channel, mixin)
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# The job that powers all the <tt>broadcast_$action_later</tt> broadcasts available in <tt>Turbo::Streams::Broadcasts</tt>.
|
2
2
|
class Turbo::Streams::ActionBroadcastJob < ActiveJob::Base
|
3
|
+
discard_on ActiveJob::DeserializationError
|
4
|
+
|
3
5
|
def perform(stream, action:, target:, **rendering)
|
4
6
|
Turbo::StreamsChannel.broadcast_action_to stream, action: action, target: target, **rendering
|
5
7
|
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# The job that powers the <tt>broadcast_render_later_to</tt> available in <tt>Turbo::Streams::Broadcasts</tt> for rendering
|
2
2
|
# turbo stream templates.
|
3
3
|
class Turbo::Streams::BroadcastJob < ActiveJob::Base
|
4
|
+
discard_on ActiveJob::DeserializationError
|
5
|
+
|
4
6
|
def perform(stream, **rendering)
|
5
7
|
Turbo::StreamsChannel.broadcast_render_to stream, **rendering
|
6
8
|
end
|
@@ -39,7 +39,7 @@ module Turbo::Broadcastable
|
|
39
39
|
module ClassMethods
|
40
40
|
# Configures the model to broadcast creates, updates, and destroys to a stream name derived at runtime by the
|
41
41
|
# <tt>stream</tt> symbol invocation. By default, the creates are appended to a dom id target name derived from
|
42
|
-
# the model's plural name. The insertion can also be made to be a prepend by overwriting <tt>
|
42
|
+
# the model's plural name. The insertion can also be made to be a prepend by overwriting <tt>inserts_by</tt> and
|
43
43
|
# the target dom id overwritten by passing <tt>target</tt>. Examples:
|
44
44
|
#
|
45
45
|
# class Message < ApplicationRecord
|
@@ -52,14 +52,14 @@ module Turbo::Broadcastable
|
|
52
52
|
# broadcasts_to ->(message) { [ message.board, :messages ] }, inserts_by: :prepend, target: "board_messages"
|
53
53
|
# end
|
54
54
|
def broadcasts_to(stream, inserts_by: :append, target: broadcast_target_default)
|
55
|
-
after_create_commit -> { broadcast_action_later_to stream.try(:call, self) || send(stream), action: inserts_by, target: target }
|
55
|
+
after_create_commit -> { broadcast_action_later_to stream.try(:call, self) || send(stream), action: inserts_by, target: target.try(:call, self) || target }
|
56
56
|
after_update_commit -> { broadcast_replace_later_to stream.try(:call, self) || send(stream) }
|
57
57
|
after_destroy_commit -> { broadcast_remove_to stream.try(:call, self) || send(stream) }
|
58
58
|
end
|
59
59
|
|
60
60
|
# Same as <tt>#broadcasts_to</tt>, but the designated stream is automatically set to the current model.
|
61
61
|
def broadcasts(inserts_by: :append, target: broadcast_target_default)
|
62
|
-
after_create_commit -> { broadcast_action_later action: inserts_by, target: target }
|
62
|
+
after_create_commit -> { broadcast_action_later action: inserts_by, target: target.try(:call, self) || target }
|
63
63
|
after_update_commit -> { broadcast_replace_later }
|
64
64
|
after_destroy_commit -> { broadcast_remove }
|
65
65
|
end
|
@@ -75,8 +75,8 @@ module Turbo::Broadcastable
|
|
75
75
|
#
|
76
76
|
# # Sends <turbo-stream action="remove" target="clearance_5"></turbo-stream> to the stream named "identity:2:clearances"
|
77
77
|
# clearance.broadcast_remove_to examiner.identity, :clearances
|
78
|
-
def broadcast_remove_to(*streamables)
|
79
|
-
Turbo::StreamsChannel.broadcast_remove_to *streamables, target:
|
78
|
+
def broadcast_remove_to(*streamables, target: self)
|
79
|
+
Turbo::StreamsChannel.broadcast_remove_to *streamables, target: target
|
80
80
|
end
|
81
81
|
|
82
82
|
# Same as <tt>#broadcast_remove_to</tt>, but the designated stream is automatically set to the current model.
|
@@ -103,6 +103,57 @@ module Turbo::Broadcastable
|
|
103
103
|
broadcast_replace_to self, **rendering
|
104
104
|
end
|
105
105
|
|
106
|
+
# Update this broadcastable model in the dom for subscribers of the stream name identified by the passed
|
107
|
+
# <tt>streamables</tt>. The rendering parameters can be set by appending named arguments to the call. Examples:
|
108
|
+
#
|
109
|
+
# # Sends <turbo-stream action="update" target="clearance_5"><template><div id="clearance_5">My Clearance</div></template></turbo-stream>
|
110
|
+
# # to the stream named "identity:2:clearances"
|
111
|
+
# clearance.broadcast_update_to examiner.identity, :clearances
|
112
|
+
#
|
113
|
+
# # Sends <turbo-stream action="update" target="clearance_5"><template><div id="clearance_5">Other partial</div></template></turbo-stream>
|
114
|
+
# # to the stream named "identity:2:clearances"
|
115
|
+
# clearance.broadcast_update_to examiner.identity, :clearances, partial: "clearances/other_partial", locals: { a: 1 }
|
116
|
+
def broadcast_update_to(*streamables, **rendering)
|
117
|
+
Turbo::StreamsChannel.broadcast_update_to *streamables, target: self, **broadcast_rendering_with_defaults(rendering)
|
118
|
+
end
|
119
|
+
|
120
|
+
# Same as <tt>#broadcast_update_to</tt>, but the designated stream is automatically set to the current model.
|
121
|
+
def broadcast_update(**rendering)
|
122
|
+
broadcast_update_to self, **rendering
|
123
|
+
end
|
124
|
+
|
125
|
+
# Insert a rendering of this broadcastable model before the target identified by it's dom id passed as <tt>target</tt>
|
126
|
+
# for subscribers of the stream name identified by the passed <tt>streamables</tt>. The rendering parameters can be set by
|
127
|
+
# appending named arguments to the call. Examples:
|
128
|
+
#
|
129
|
+
# # Sends <turbo-stream action="before" target="clearance_5"><template><div id="clearance_4">My Clearance</div></template></turbo-stream>
|
130
|
+
# # to the stream named "identity:2:clearances"
|
131
|
+
# clearance.broadcast_before_to examiner.identity, :clearances, target: "clearance_5"
|
132
|
+
#
|
133
|
+
# # Sends <turbo-stream action="before" target="clearance_5"><template><div id="clearance_4">Other partial</div></template></turbo-stream>
|
134
|
+
# # to the stream named "identity:2:clearances"
|
135
|
+
# clearance.broadcast_before_to examiner.identity, :clearances, target: "clearance_5",
|
136
|
+
# partial: "clearances/other_partial", locals: { a: 1 }
|
137
|
+
def broadcast_before_to(*streamables, target:, **rendering)
|
138
|
+
Turbo::StreamsChannel.broadcast_before_to *streamables, target: target, **broadcast_rendering_with_defaults(rendering)
|
139
|
+
end
|
140
|
+
|
141
|
+
# Insert a rendering of this broadcastable model after the target identified by it's dom id passed as <tt>target</tt>
|
142
|
+
# for subscribers of the stream name identified by the passed <tt>streamables</tt>. The rendering parameters can be set by
|
143
|
+
# appending named arguments to the call. Examples:
|
144
|
+
#
|
145
|
+
# # Sends <turbo-stream action="after" target="clearance_5"><template><div id="clearance_6">My Clearance</div></template></turbo-stream>
|
146
|
+
# # to the stream named "identity:2:clearances"
|
147
|
+
# clearance.broadcast_after_to examiner.identity, :clearances, target: "clearance_5"
|
148
|
+
#
|
149
|
+
# # Sends <turbo-stream action="after" target="clearance_5"><template><div id="clearance_6">Other partial</div></template></turbo-stream>
|
150
|
+
# # to the stream named "identity:2:clearances"
|
151
|
+
# clearance.broadcast_after_to examiner.identity, :clearances, target: "clearance_5",
|
152
|
+
# partial: "clearances/other_partial", locals: { a: 1 }
|
153
|
+
def broadcast_after_to(*streamables, target:, **rendering)
|
154
|
+
Turbo::StreamsChannel.broadcast_after_to *streamables, target: target, **broadcast_rendering_with_defaults(rendering)
|
155
|
+
end
|
156
|
+
|
106
157
|
# Append a rendering of this broadcastable model to the target identified by it's dom id passed as <tt>target</tt>
|
107
158
|
# for subscribers of the stream name identified by the passed <tt>streamables</tt>. The rendering parameters can be set by
|
108
159
|
# appending named arguments to the call. Examples:
|
@@ -140,7 +191,7 @@ module Turbo::Broadcastable
|
|
140
191
|
Turbo::StreamsChannel.broadcast_prepend_to *streamables, target: target, **broadcast_rendering_with_defaults(rendering)
|
141
192
|
end
|
142
193
|
|
143
|
-
# Same as <tt>#
|
194
|
+
# Same as <tt>#broadcast_prepend_to</tt>, but the designated stream is automatically set to the current model.
|
144
195
|
def broadcast_prepend(target: broadcast_target_default, **rendering)
|
145
196
|
broadcast_prepend_to self, target: target, **rendering
|
146
197
|
end
|
@@ -170,6 +221,16 @@ module Turbo::Broadcastable
|
|
170
221
|
broadcast_replace_later_to self, **rendering
|
171
222
|
end
|
172
223
|
|
224
|
+
# Same as <tt>broadcast_update_to</tt> but run asynchronously via a <tt>Turbo::Streams::BroadcastJob</tt>.
|
225
|
+
def broadcast_update_later_to(*streamables, **rendering)
|
226
|
+
Turbo::StreamsChannel.broadcast_update_later_to *streamables, target: self, **broadcast_rendering_with_defaults(rendering)
|
227
|
+
end
|
228
|
+
|
229
|
+
# Same as <tt>#broadcast_update_later_to</tt>, but the designated stream is automatically set to the current model.
|
230
|
+
def broadcast_update_later(**rendering)
|
231
|
+
broadcast_update_later_to self, **rendering
|
232
|
+
end
|
233
|
+
|
173
234
|
# Same as <tt>broadcast_append_to</tt> but run asynchronously via a <tt>Turbo::Streams::BroadcastJob</tt>.
|
174
235
|
def broadcast_append_later_to(*streamables, target: broadcast_target_default, **rendering)
|
175
236
|
Turbo::StreamsChannel.broadcast_append_later_to *streamables, target: target, **broadcast_rendering_with_defaults(rendering)
|
@@ -190,7 +251,7 @@ module Turbo::Broadcastable
|
|
190
251
|
broadcast_prepend_later_to self, target: target, **rendering
|
191
252
|
end
|
192
253
|
|
193
|
-
# Same as <tt>
|
254
|
+
# Same as <tt>broadcast_action_to</tt> but run asynchronously via a <tt>Turbo::Streams::BroadcastJob</tt>.
|
194
255
|
def broadcast_action_later_to(*streamables, action:, target: broadcast_target_default, **rendering)
|
195
256
|
Turbo::StreamsChannel.broadcast_action_later_to(*streamables, action: action, target: target, **broadcast_rendering_with_defaults(rendering))
|
196
257
|
end
|
@@ -219,7 +280,7 @@ module Turbo::Broadcastable
|
|
219
280
|
broadcast_render_later_to self, **rendering
|
220
281
|
end
|
221
282
|
|
222
|
-
# Same as <tt>
|
283
|
+
# Same as <tt>broadcast_render_later</tt> but run with the added option of naming the stream using the passed
|
223
284
|
# <tt>streamables</tt>.
|
224
285
|
def broadcast_render_later_to(*streamables, **rendering)
|
225
286
|
Turbo::StreamsChannel.broadcast_render_later_to *streamables, **broadcast_rendering_with_defaults(rendering)
|
@@ -233,7 +294,9 @@ module Turbo::Broadcastable
|
|
233
294
|
|
234
295
|
def broadcast_rendering_with_defaults(options)
|
235
296
|
options.tap do |o|
|
236
|
-
|
297
|
+
# Add the current instance into the locals with the element name (which is the un-namespaced name)
|
298
|
+
# as the key. This parallels how the ActionView::ObjectRenderer would create a local variable.
|
299
|
+
o[:locals] = (o[:locals] || {}).reverse_merge!(model_name.element.to_sym => self)
|
237
300
|
o[:partial] ||= to_partial_path
|
238
301
|
end
|
239
302
|
end
|
@@ -40,6 +40,16 @@ class Turbo::Streams::TagBuilder
|
|
40
40
|
action :remove, target, allow_inferred_rendering: false
|
41
41
|
end
|
42
42
|
|
43
|
+
# Removes the <tt>targets</tt> from the dom. The targets can either be a CSS selector string or an object that responds to
|
44
|
+
# <tt>to_key</tt>, which is then called and passed through <tt>ActionView::RecordIdentifier.dom_id</tt> (all Active Records
|
45
|
+
# do). Examples:
|
46
|
+
#
|
47
|
+
# <%= turbo_stream.remove_all ".clearance_item" %>
|
48
|
+
# <%= turbo_stream.remove_all clearance %>
|
49
|
+
def remove_all(targets)
|
50
|
+
action_all :remove, targets, allow_inferred_rendering: false
|
51
|
+
end
|
52
|
+
|
43
53
|
# Replace the <tt>target</tt> in the dom with the either the <tt>content</tt> passed in, a rendering result determined
|
44
54
|
# by the <tt>rendering</tt> keyword arguments, the content in the block, or the rendering of the target as a record. Examples:
|
45
55
|
#
|
@@ -53,6 +63,71 @@ class Turbo::Streams::TagBuilder
|
|
53
63
|
action :replace, target, content, **rendering, &block
|
54
64
|
end
|
55
65
|
|
66
|
+
# Replace the <tt>targets</tt> in the dom with the either the <tt>content</tt> passed in, a rendering result determined
|
67
|
+
# by the <tt>rendering</tt> keyword arguments, the content in the block, or the rendering of the target as a record. Examples:
|
68
|
+
#
|
69
|
+
# <%= turbo_stream.replace_all ".clearance_item", "<div class='clearance_item'>Replace the dom target identified by the class clearance_item</div>" %>
|
70
|
+
# <%= turbo_stream.replace_all clearance %>
|
71
|
+
# <%= turbo_stream.replace_all clearance, partial: "clearances/clearance", locals: { title: "Hello" } %>
|
72
|
+
# <%= turbo_stream.replace_all ".clearance_item" do %>
|
73
|
+
# <div class='.clearance_item'>Replace the dom target identified by the class clearance_item</div>
|
74
|
+
# <% end %>
|
75
|
+
def replace_all(targets, content = nil, **rendering, &block)
|
76
|
+
action_all :replace, targets, content, **rendering, &block
|
77
|
+
end
|
78
|
+
|
79
|
+
# Insert the <tt>content</tt> passed in, a rendering result determined by the <tt>rendering</tt> keyword arguments,
|
80
|
+
# the content in the block, or the rendering of the target as a record before the <tt>target</tt> in the dom. Examples:
|
81
|
+
#
|
82
|
+
# <%= turbo_stream.before "clearance_5", "<div id='clearance_4'>Insert before the dom target identified by clearance_5</div>" %>
|
83
|
+
# <%= turbo_stream.before clearance %>
|
84
|
+
# <%= turbo_stream.before clearance, partial: "clearances/clearance", locals: { title: "Hello" } %>
|
85
|
+
# <%= turbo_stream.before "clearance_5" do %>
|
86
|
+
# <div id='clearance_4'>Insert before the dom target identified by clearance_5</div>
|
87
|
+
# <% end %>
|
88
|
+
def before(target, content = nil, **rendering, &block)
|
89
|
+
action :before, target, content, **rendering, &block
|
90
|
+
end
|
91
|
+
|
92
|
+
# Insert the <tt>content</tt> passed in, a rendering result determined by the <tt>rendering</tt> keyword arguments,
|
93
|
+
# the content in the block, or the rendering of the target as a record before the <tt>targets</tt> in the dom. Examples:
|
94
|
+
#
|
95
|
+
# <%= turbo_stream.before_all ".clearance_item", "<div class='clearance_item'>Insert before the dom target identified by the class clearance_item</div>" %>
|
96
|
+
# <%= turbo_stream.before_all clearance %>
|
97
|
+
# <%= turbo_stream.before_all clearance, partial: "clearances/clearance", locals: { title: "Hello" } %>
|
98
|
+
# <%= turbo_stream.before_all ".clearance_item" do %>
|
99
|
+
# <div class='clearance_item'>Insert before the dom target identified by clearance_item</div>
|
100
|
+
# <% end %>
|
101
|
+
def before_all(targets, content = nil, **rendering, &block)
|
102
|
+
action_all :before, targets, content, **rendering, &block
|
103
|
+
end
|
104
|
+
|
105
|
+
# Insert the <tt>content</tt> passed in, a rendering result determined by the <tt>rendering</tt> keyword arguments,
|
106
|
+
# the content in the block, or the rendering of the target as a record after the <tt>target</tt> in the dom. Examples:
|
107
|
+
#
|
108
|
+
# <%= turbo_stream.after "clearance_5", "<div id='clearance_6'>Insert after the dom target identified by clearance_5</div>" %>
|
109
|
+
# <%= turbo_stream.after clearance %>
|
110
|
+
# <%= turbo_stream.after clearance, partial: "clearances/clearance", locals: { title: "Hello" } %>
|
111
|
+
# <%= turbo_stream.after "clearance_5" do %>
|
112
|
+
# <div id='clearance_6'>Insert after the dom target identified by clearance_5</div>
|
113
|
+
# <% end %>
|
114
|
+
def after(target, content = nil, **rendering, &block)
|
115
|
+
action :after, target, content, **rendering, &block
|
116
|
+
end
|
117
|
+
|
118
|
+
# Insert the <tt>content</tt> passed in, a rendering result determined by the <tt>rendering</tt> keyword arguments,
|
119
|
+
# the content in the block, or the rendering of the target as a record after the <tt>targets</tt> in the dom. Examples:
|
120
|
+
#
|
121
|
+
# <%= turbo_stream.after_all ".clearance_item", "<div class='clearance_item'>Insert after the dom target identified by the class clearance_item</div>" %>
|
122
|
+
# <%= turbo_stream.after_all clearance %>
|
123
|
+
# <%= turbo_stream.after_all clearance, partial: "clearances/clearance", locals: { title: "Hello" } %>
|
124
|
+
# <%= turbo_stream.after_all "clearance_item" do %>
|
125
|
+
# <div class='clearance_item'>Insert after the dom target identified by the class clearance_item</div>
|
126
|
+
# <% end %>
|
127
|
+
def after_all(targets, content = nil, **rendering, &block)
|
128
|
+
action_all :after, targets, content, **rendering, &block
|
129
|
+
end
|
130
|
+
|
56
131
|
# Update the <tt>target</tt> in the dom with the either the <tt>content</tt> passed in or a rendering result determined
|
57
132
|
# by the <tt>rendering</tt> keyword arguments, the content in the block, or the rendering of the target as a record. Examples:
|
58
133
|
#
|
@@ -66,6 +141,19 @@ class Turbo::Streams::TagBuilder
|
|
66
141
|
action :update, target, content, **rendering, &block
|
67
142
|
end
|
68
143
|
|
144
|
+
# Update the <tt>targets</tt> in the dom with the either the <tt>content</tt> passed in or a rendering result determined
|
145
|
+
# by the <tt>rendering</tt> keyword arguments, the content in the block, or the rendering of the targets as a record. Examples:
|
146
|
+
#
|
147
|
+
# <%= turbo_stream.update_all "clearance_item", "Update the content of the dom target identified by the class clearance_item" %>
|
148
|
+
# <%= turbo_stream.update_all clearance %>
|
149
|
+
# <%= turbo_stream.update_all clearance, partial: "clearances/new_clearance", locals: { title: "Hello" } %>
|
150
|
+
# <%= turbo_stream.update_all "clearance_item" do %>
|
151
|
+
# Update the content of the dom target identified by the class clearance_item
|
152
|
+
# <% end %>
|
153
|
+
def update_all(targets, content = nil, **rendering, &block)
|
154
|
+
action_all :update, targets, content, **rendering, &block
|
155
|
+
end
|
156
|
+
|
69
157
|
# Append to the target in the dom identified with <tt>target</tt> either the <tt>content</tt> passed in or a
|
70
158
|
# rendering result determined by the <tt>rendering</tt> keyword arguments, the content in the block,
|
71
159
|
# or the rendering of the content as a record. Examples:
|
@@ -80,6 +168,20 @@ class Turbo::Streams::TagBuilder
|
|
80
168
|
action :append, target, content, **rendering, &block
|
81
169
|
end
|
82
170
|
|
171
|
+
# Append to the targets in the dom identified with <tt>targets</tt> either the <tt>content</tt> passed in or a
|
172
|
+
# rendering result determined by the <tt>rendering</tt> keyword arguments, the content in the block,
|
173
|
+
# or the rendering of the content as a record. Examples:
|
174
|
+
#
|
175
|
+
# <%= turbo_stream.append_all ".clearances", "<div class='clearance_item'>Append this to .clearance_group</div>" %>
|
176
|
+
# <%= turbo_stream.append_all ".clearances", clearance %>
|
177
|
+
# <%= turbo_stream.append_all ".clearances", partial: "clearances/new_clearance", locals: { clearance: clearance } %>
|
178
|
+
# <%= turbo_stream.append_all ".clearances" do %>
|
179
|
+
# <div id='clearance_item'>Append this to .clearances</div>
|
180
|
+
# <% end %>
|
181
|
+
def append_all(targets, content = nil, **rendering, &block)
|
182
|
+
action_all :append, targets, content, **rendering, &block
|
183
|
+
end
|
184
|
+
|
83
185
|
# Prepend to the target in the dom identified with <tt>target</tt> either the <tt>content</tt> passed in or a
|
84
186
|
# rendering result determined by the <tt>rendering</tt> keyword arguments or the content in the block,
|
85
187
|
# or the rendering of the content as a record. Examples:
|
@@ -94,20 +196,34 @@ class Turbo::Streams::TagBuilder
|
|
94
196
|
action :prepend, target, content, **rendering, &block
|
95
197
|
end
|
96
198
|
|
97
|
-
#
|
199
|
+
# Prepend to the targets in the dom identified with <tt>targets</tt> either the <tt>content</tt> passed in or a
|
200
|
+
# rendering result determined by the <tt>rendering</tt> keyword arguments or the content in the block,
|
201
|
+
# or the rendering of the content as a record. Examples:
|
202
|
+
#
|
203
|
+
# <%= turbo_stream.prepend_all ".clearances", "<div class='clearance_item'>Prepend this to .clearances</div>" %>
|
204
|
+
# <%= turbo_stream.prepend_all ".clearances", clearance %>
|
205
|
+
# <%= turbo_stream.prepend_all ".clearances", partial: "clearances/new_clearance", locals: { clearance: clearance } %>
|
206
|
+
# <%= turbo_stream.prepend_all ".clearances" do %>
|
207
|
+
# <div class='clearance_item'>Prepend this to .clearances</div>
|
208
|
+
# <% end %>
|
209
|
+
def prepend_all(targets, content = nil, **rendering, &block)
|
210
|
+
action_all :prepend, targets, content, **rendering, &block
|
211
|
+
end
|
212
|
+
|
213
|
+
# Send an action of the type <tt>name</tt> to <tt>target</tt>. Options described in the concrete methods.
|
98
214
|
def action(name, target, content = nil, allow_inferred_rendering: true, **rendering, &block)
|
99
215
|
target_name = extract_target_name_from(target)
|
216
|
+
template = render_template(target, content, allow_inferred_rendering: allow_inferred_rendering, **rendering, &block)
|
100
217
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
end
|
218
|
+
turbo_stream_action_tag name, target: target_name, template: template
|
219
|
+
end
|
220
|
+
|
221
|
+
# Send an action of the type <tt>name</tt> to <tt>targets</tt>. Options described in the concrete methods.
|
222
|
+
def action_all(name, targets, content = nil, allow_inferred_rendering: true, **rendering, &block)
|
223
|
+
targets_name = extract_target_name_from(targets)
|
224
|
+
template = render_template(targets, content, allow_inferred_rendering: allow_inferred_rendering, **rendering, &block)
|
225
|
+
|
226
|
+
turbo_stream_action_tag name, targets: targets_name, template: template
|
111
227
|
end
|
112
228
|
|
113
229
|
private
|
@@ -119,6 +235,19 @@ class Turbo::Streams::TagBuilder
|
|
119
235
|
end
|
120
236
|
end
|
121
237
|
|
238
|
+
def render_template(target, content = nil, allow_inferred_rendering: true, **rendering, &block)
|
239
|
+
case
|
240
|
+
when content
|
241
|
+
allow_inferred_rendering ? (render_record(content) || content) : content
|
242
|
+
when block_given?
|
243
|
+
@view_context.capture(&block)
|
244
|
+
when rendering.any?
|
245
|
+
@view_context.render(formats: [ :html ], **rendering)
|
246
|
+
else
|
247
|
+
render_record(target) if allow_inferred_rendering
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
122
251
|
def render_record(possible_record)
|
123
252
|
if possible_record.respond_to?(:to_partial_path)
|
124
253
|
record = possible_record
|