turbo-rails 0.7.11 → 0.7.15

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: 0fe3ad5cd094491982825ff80d21c619aab81bbcbe7e07168e467beeb3daa493
4
- data.tar.gz: 757f2faa9d39389014fc277ef75d3c806c9864b1deb87f6efae5118c604cf89b
3
+ metadata.gz: ab24210e4f0dd28243c220d5b586b69705e2b18b50251daa22e8cd6d861fc9f5
4
+ data.tar.gz: 7379f1f27936571fe482807459f18f773c041d36ae539cd0e1750dd5ade8489b
5
5
  SHA512:
6
- metadata.gz: e38bd507e3eaeeccd3e8e570e3341cdc8ae27074ba03d3e509605a13f3df4188bd54250bbbb8f6161e3d3e261e5ae6edd928d3fb2aac7fd8d9ede9e7c1810717
7
- data.tar.gz: 77f0a351ce8ab0cca1bc69413a508d6d8b790f61e18623ae16aad7d929536baa4f8c75b6407e6752d5301d022f0b49472c4376506181d1ffd31ed91b033459a2
6
+ metadata.gz: fa92baea7d57b563f9c802e3a595a870f5c3fe38402c49720cd34908a6c396a3fcdb503fc8be035407ff3c8bdad8bcb81294fa83d81dc2e53d676de49da5cd50
7
+ data.tar.gz: b3a8d8bd0ff379e6dd40c8a41e53aa413c914c04cdf9cc2408fc1c670b3bafde13881bd4fc2a9b106e77c09ee770e61061cce8c8ddf69d0160b759995a93883e
data/README.md CHANGED
@@ -71,10 +71,7 @@ Turbo can coexist with Rails UJS, but you need to take a series of upgrade steps
71
71
 
72
72
  ## Development
73
73
 
74
- * To run the Rails tests: `bundle exec rake`.
75
- * To install dependencies: `bundle install`
76
- * To prepare the test database: `cd test/dummy; RAILS_ENV=test ./bin/rails db:migrate`
77
- * To compile the JavaScript for the asset pipeline: `yarn build`
74
+ Run the tests with `./bin/test`.
78
75
 
79
76
 
80
77
  ## License
@@ -31,6 +31,7 @@ function clickCaptured(event) {
31
31
 
32
32
  (function() {
33
33
  if ("SubmitEvent" in window) return;
34
+ if ("submitter" in Event.prototype) return;
34
35
  addEventListener("click", clickCaptured, true);
35
36
  Object.defineProperty(Event.prototype, "submitter", {
36
37
  get() {
@@ -226,11 +227,11 @@ class FetchResponse {
226
227
  return this.header("Content-Type");
227
228
  }
228
229
  get responseText() {
229
- return this.response.text();
230
+ return this.response.clone().text();
230
231
  }
231
232
  get responseHTML() {
232
233
  if (this.isHTML) {
233
- return this.response.text();
234
+ return this.response.clone().text();
234
235
  } else {
235
236
  return Promise.resolve(undefined);
236
237
  }
@@ -246,7 +247,11 @@ function dispatch(eventName, {target: target, cancelable: cancelable, detail: de
246
247
  bubbles: true,
247
248
  detail: detail
248
249
  });
249
- void (target || document.documentElement).dispatchEvent(event);
250
+ if (target && target.isConnected) {
251
+ target.dispatchEvent(event);
252
+ } else {
253
+ document.documentElement.dispatchEvent(event);
254
+ }
250
255
  return event;
251
256
  }
252
257
 
@@ -326,7 +331,7 @@ function fetchMethodFromString(method) {
326
331
  }
327
332
 
328
333
  class FetchRequest {
329
- constructor(delegate, method, location, body = new URLSearchParams) {
334
+ constructor(delegate, method, location, body = new URLSearchParams, target = null) {
330
335
  this.abortController = new AbortController;
331
336
  this.resolveRequestPromise = value => {};
332
337
  this.delegate = delegate;
@@ -338,6 +343,7 @@ class FetchRequest {
338
343
  this.body = body;
339
344
  this.url = location;
340
345
  }
346
+ this.target = target;
341
347
  }
342
348
  get location() {
343
349
  return this.url;
@@ -375,7 +381,8 @@ class FetchRequest {
375
381
  cancelable: true,
376
382
  detail: {
377
383
  fetchResponse: fetchResponse
378
- }
384
+ },
385
+ target: this.target
379
386
  });
380
387
  if (event.defaultPrevented) {
381
388
  this.delegate.requestPreventedHandlingResponse(this, fetchResponse);
@@ -417,7 +424,8 @@ class FetchRequest {
417
424
  fetchOptions: fetchOptions,
418
425
  url: this.url.href,
419
426
  resume: this.resolveRequestPromise
420
- }
427
+ },
428
+ target: this.target
421
429
  });
422
430
  if (event.defaultPrevented) await requestInterception;
423
431
  }
@@ -538,7 +546,7 @@ class FormSubmission {
538
546
  this.formElement = formElement;
539
547
  this.submitter = submitter;
540
548
  this.formData = buildFormData(formElement, submitter);
541
- this.fetchRequest = new FetchRequest(this, this.method, this.location, this.body);
549
+ this.fetchRequest = new FetchRequest(this, this.method, this.location, this.body, this.formElement);
542
550
  this.mustRedirect = mustRedirect;
543
551
  }
544
552
  get method() {
@@ -1173,7 +1181,7 @@ ProgressBar.animationDuration = 300;
1173
1181
  class HeadSnapshot extends Snapshot {
1174
1182
  constructor() {
1175
1183
  super(...arguments);
1176
- this.detailsByOuterHTML = this.children.filter((element => !elementIsNoscript(element))).reduce(((result, element) => {
1184
+ this.detailsByOuterHTML = this.children.filter((element => !elementIsNoscript(element))).map((element => elementWithoutNonce(element))).reduce(((result, element) => {
1177
1185
  const {outerHTML: outerHTML} = element;
1178
1186
  const details = outerHTML in result ? result[outerHTML] : {
1179
1187
  type: elementType(element),
@@ -1255,6 +1263,13 @@ function elementIsMetaElementWithName(element, name) {
1255
1263
  return tagName == "meta" && element.getAttribute("name") == name;
1256
1264
  }
1257
1265
 
1266
+ function elementWithoutNonce(element) {
1267
+ if (element.hasAttribute("nonce")) {
1268
+ element.setAttribute("nonce", "");
1269
+ }
1270
+ return element;
1271
+ }
1272
+
1258
1273
  class PageSnapshot extends Snapshot {
1259
1274
  constructor(element, headSnapshot) {
1260
1275
  super(element);
@@ -1805,18 +1820,18 @@ class FrameRedirector {
1805
1820
  return this.shouldRedirect(element, submitter);
1806
1821
  }
1807
1822
  formSubmissionIntercepted(element, submitter) {
1808
- const frame = this.findFrameElement(element);
1823
+ const frame = this.findFrameElement(element, submitter);
1809
1824
  if (frame) {
1810
1825
  frame.removeAttribute("reloadable");
1811
1826
  frame.delegate.formSubmissionIntercepted(element, submitter);
1812
1827
  }
1813
1828
  }
1814
1829
  shouldRedirect(element, submitter) {
1815
- const frame = this.findFrameElement(element);
1830
+ const frame = this.findFrameElement(element, submitter);
1816
1831
  return frame ? frame != element.closest("turbo-frame") : false;
1817
1832
  }
1818
- findFrameElement(element) {
1819
- const id = element.getAttribute("data-turbo-frame");
1833
+ findFrameElement(element, submitter) {
1834
+ const id = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("data-turbo-frame")) || element.getAttribute("data-turbo-frame");
1820
1835
  if (id && id != "_top") {
1821
1836
  const frame = this.element.querySelector(`#${id}:not([disabled])`);
1822
1837
  if (frame instanceof FrameElement) {
@@ -2539,12 +2554,14 @@ class Session {
2539
2554
  });
2540
2555
  }
2541
2556
  convertLinkWithMethodClickToFormSubmission(link) {
2557
+ var _a;
2542
2558
  const linkMethod = link.getAttribute("data-turbo-method");
2543
2559
  if (linkMethod) {
2544
2560
  const form = document.createElement("form");
2545
2561
  form.method = linkMethod;
2546
2562
  form.action = link.getAttribute("href") || "undefined";
2547
- document.body.appendChild(form);
2563
+ form.hidden = true;
2564
+ (_a = link.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(form, link);
2548
2565
  return dispatch("submit", {
2549
2566
  cancelable: true,
2550
2567
  target: form
@@ -2896,7 +2913,7 @@ class FrameController {
2896
2913
  this.reloadable = false;
2897
2914
  this.formSubmission = new FormSubmission(this, element, submitter);
2898
2915
  if (this.formSubmission.fetchRequest.isIdempotent) {
2899
- this.navigateFrame(element, this.formSubmission.fetchRequest.url.href);
2916
+ this.navigateFrame(element, this.formSubmission.fetchRequest.url.href, submitter);
2900
2917
  } else {
2901
2918
  const {fetchRequest: fetchRequest} = this.formSubmission;
2902
2919
  this.prepareHeadersForRequest(fetchRequest.headers, fetchRequest);
@@ -2932,7 +2949,7 @@ class FrameController {
2932
2949
  frame.setAttribute("busy", "");
2933
2950
  }
2934
2951
  formSubmissionSucceededWithResponse(formSubmission, response) {
2935
- const frame = this.findFrameElement(formSubmission.formElement);
2952
+ const frame = this.findFrameElement(formSubmission.formElement, formSubmission.submitter);
2936
2953
  frame.delegate.loadResponse(response);
2937
2954
  }
2938
2955
  formSubmissionFailedWithResponse(formSubmission, fetchResponse) {
@@ -2951,7 +2968,7 @@ class FrameController {
2951
2968
  viewRenderedSnapshot(snapshot, isPreview) {}
2952
2969
  viewInvalidated() {}
2953
2970
  async visit(url) {
2954
- const request = new FetchRequest(this, FetchMethod.get, expandURL(url));
2971
+ const request = new FetchRequest(this, FetchMethod.get, expandURL(url), undefined, this.element);
2955
2972
  return new Promise((resolve => {
2956
2973
  this.resolveVisitPromise = () => {
2957
2974
  this.resolveVisitPromise = () => {};
@@ -2960,13 +2977,14 @@ class FrameController {
2960
2977
  request.perform();
2961
2978
  }));
2962
2979
  }
2963
- navigateFrame(element, url) {
2964
- const frame = this.findFrameElement(element);
2980
+ navigateFrame(element, url, submitter) {
2981
+ const frame = this.findFrameElement(element, submitter);
2982
+ frame.setAttribute("reloadable", "");
2965
2983
  frame.src = url;
2966
2984
  }
2967
- findFrameElement(element) {
2985
+ findFrameElement(element, submitter) {
2968
2986
  var _a;
2969
- const id = element.getAttribute("data-turbo-frame") || this.element.getAttribute("target");
2987
+ const id = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("data-turbo-frame")) || element.getAttribute("data-turbo-frame") || this.element.getAttribute("target");
2970
2988
  return (_a = getFrameElementById(id)) !== null && _a !== void 0 ? _a : this.element;
2971
2989
  }
2972
2990
  async extractForeignFrameElement(container) {
@@ -2987,7 +3005,7 @@ class FrameController {
2987
3005
  return new FrameElement;
2988
3006
  }
2989
3007
  shouldInterceptNavigation(element, submitter) {
2990
- const id = element.getAttribute("data-turbo-frame") || this.element.getAttribute("target");
3008
+ const id = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("data-turbo-frame")) || element.getAttribute("data-turbo-frame") || this.element.getAttribute("target");
2991
3009
  if (!this.enabled || id == "_top") {
2992
3010
  return false;
2993
3011
  }
@@ -6,61 +6,61 @@ module Turbo::Streams::Broadcasts
6
6
  include Turbo::Streams::ActionHelper
7
7
 
8
8
  def broadcast_remove_to(*streamables, **opts)
9
- broadcast_action_to *streamables, action: :remove, **opts
9
+ broadcast_action_to(*streamables, action: :remove, **opts)
10
10
  end
11
11
 
12
12
  def broadcast_replace_to(*streamables, **opts)
13
- broadcast_action_to *streamables, action: :replace, **opts
13
+ broadcast_action_to(*streamables, action: :replace, **opts)
14
14
  end
15
15
 
16
16
  def broadcast_update_to(*streamables, **opts)
17
- broadcast_action_to *streamables, action: :update, **opts
17
+ broadcast_action_to(*streamables, action: :update, **opts)
18
18
  end
19
19
 
20
20
  def broadcast_before_to(*streamables, **opts)
21
- broadcast_action_to *streamables, action: :before, **opts
21
+ broadcast_action_to(*streamables, action: :before, **opts)
22
22
  end
23
23
 
24
24
  def broadcast_after_to(*streamables, **opts)
25
- broadcast_action_to *streamables, action: :after, **opts
25
+ broadcast_action_to(*streamables, action: :after, **opts)
26
26
  end
27
27
 
28
28
  def broadcast_append_to(*streamables, **opts)
29
- broadcast_action_to *streamables, action: :append, **opts
29
+ broadcast_action_to(*streamables, action: :append, **opts)
30
30
  end
31
31
 
32
32
  def broadcast_prepend_to(*streamables, **opts)
33
- broadcast_action_to *streamables, action: :prepend, **opts
33
+ broadcast_action_to(*streamables, action: :prepend, **opts)
34
34
  end
35
35
 
36
36
  def broadcast_action_to(*streamables, action:, target: nil, targets: nil, **rendering)
37
- broadcast_stream_to *streamables, content: turbo_stream_action_tag(action, target: target, targets: targets, template:
37
+ broadcast_stream_to(*streamables, content: turbo_stream_action_tag(action, target: target, targets: targets, template:
38
38
  rendering.delete(:content) || (rendering.any? ? render_format(:html, **rendering) : nil)
39
- )
39
+ ))
40
40
  end
41
41
 
42
42
  def broadcast_replace_later_to(*streamables, **opts)
43
- broadcast_action_later_to *streamables, action: :replace, **opts
43
+ broadcast_action_later_to(*streamables, action: :replace, **opts)
44
44
  end
45
45
 
46
46
  def broadcast_update_later_to(*streamables, **opts)
47
- broadcast_action_later_to *streamables, action: :update, **opts
47
+ broadcast_action_later_to(*streamables, action: :update, **opts)
48
48
  end
49
49
 
50
50
  def broadcast_before_later_to(*streamables, **opts)
51
- broadcast_action_later_to *streamables, action: :before, **opts
51
+ broadcast_action_later_to(*streamables, action: :before, **opts)
52
52
  end
53
53
 
54
54
  def broadcast_after_later_to(*streamables, **opts)
55
- broadcast_action_later_to *streamables, action: :after, **opts
55
+ broadcast_action_later_to(*streamables, action: :after, **opts)
56
56
  end
57
57
 
58
58
  def broadcast_append_later_to(*streamables, **opts)
59
- broadcast_action_later_to *streamables, action: :append, **opts
59
+ broadcast_action_later_to(*streamables, action: :append, **opts)
60
60
  end
61
61
 
62
62
  def broadcast_prepend_later_to(*streamables, **opts)
63
- broadcast_action_later_to *streamables, action: :prepend, **opts
63
+ broadcast_action_later_to(*streamables, action: :prepend, **opts)
64
64
  end
65
65
 
66
66
  def broadcast_action_later_to(*streamables, action:, target: nil, targets: nil, **rendering)
@@ -69,7 +69,7 @@ module Turbo::Streams::Broadcasts
69
69
  end
70
70
 
71
71
  def broadcast_render_to(*streamables, **rendering)
72
- broadcast_stream_to *streamables, content: render_format(:turbo_stream, **rendering)
72
+ broadcast_stream_to(*streamables, content: render_format(:turbo_stream, **rendering))
73
73
  end
74
74
 
75
75
  def broadcast_render_later_to(*streamables, **rendering)
@@ -14,7 +14,7 @@ module Turbo::Streams::ActionHelper
14
14
 
15
15
  if target = convert_to_turbo_stream_dom_id(target)
16
16
  %(<turbo-stream action="#{action}" target="#{target}">#{template}</turbo-stream>).html_safe
17
- elsif targets = convert_to_turbo_stream_dom_id(targets)
17
+ elsif targets = convert_to_turbo_stream_dom_id(targets, include_selector: true)
18
18
  %(<turbo-stream action="#{action}" targets="#{targets}">#{template}</turbo-stream>).html_safe
19
19
  else
20
20
  raise ArgumentError, "target or targets must be supplied"
@@ -22,7 +22,11 @@ module Turbo::Streams::ActionHelper
22
22
  end
23
23
 
24
24
  private
25
- def convert_to_turbo_stream_dom_id(target)
26
- target.respond_to?(:to_key) ? ActionView::RecordIdentifier.dom_id(target) : target
25
+ def convert_to_turbo_stream_dom_id(target, include_selector: false)
26
+ if target.respond_to?(:to_key)
27
+ [ ("#" if include_selector), ActionView::RecordIdentifier.dom_id(target) ].compact.join
28
+ else
29
+ target
30
+ end
27
31
  end
28
32
  end
@@ -76,7 +76,7 @@ module Turbo::Broadcastable
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
78
  def broadcast_remove_to(*streamables, target: self)
79
- Turbo::StreamsChannel.broadcast_remove_to *streamables, target: target
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.
@@ -95,7 +95,7 @@ module Turbo::Broadcastable
95
95
  # # to the stream named "identity:2:clearances"
96
96
  # clearance.broadcast_replace_to examiner.identity, :clearances, partial: "clearances/other_partial", locals: { a: 1 }
97
97
  def broadcast_replace_to(*streamables, **rendering)
98
- Turbo::StreamsChannel.broadcast_replace_to *streamables, target: self, **broadcast_rendering_with_defaults(rendering)
98
+ Turbo::StreamsChannel.broadcast_replace_to(*streamables, target: self, **broadcast_rendering_with_defaults(rendering))
99
99
  end
100
100
 
101
101
  # Same as <tt>#broadcast_replace_to</tt>, but the designated stream is automatically set to the current model.
@@ -114,7 +114,7 @@ module Turbo::Broadcastable
114
114
  # # to the stream named "identity:2:clearances"
115
115
  # clearance.broadcast_update_to examiner.identity, :clearances, partial: "clearances/other_partial", locals: { a: 1 }
116
116
  def broadcast_update_to(*streamables, **rendering)
117
- Turbo::StreamsChannel.broadcast_update_to *streamables, target: self, **broadcast_rendering_with_defaults(rendering)
117
+ Turbo::StreamsChannel.broadcast_update_to(*streamables, target: self, **broadcast_rendering_with_defaults(rendering))
118
118
  end
119
119
 
120
120
  # Same as <tt>#broadcast_update_to</tt>, but the designated stream is automatically set to the current model.
@@ -135,7 +135,7 @@ module Turbo::Broadcastable
135
135
  # clearance.broadcast_before_to examiner.identity, :clearances, target: "clearance_5",
136
136
  # partial: "clearances/other_partial", locals: { a: 1 }
137
137
  def broadcast_before_to(*streamables, target:, **rendering)
138
- Turbo::StreamsChannel.broadcast_before_to *streamables, target: target, **broadcast_rendering_with_defaults(rendering)
138
+ Turbo::StreamsChannel.broadcast_before_to(*streamables, target: target, **broadcast_rendering_with_defaults(rendering))
139
139
  end
140
140
 
141
141
  # Insert a rendering of this broadcastable model after the target identified by it's dom id passed as <tt>target</tt>
@@ -151,7 +151,7 @@ module Turbo::Broadcastable
151
151
  # clearance.broadcast_after_to examiner.identity, :clearances, target: "clearance_5",
152
152
  # partial: "clearances/other_partial", locals: { a: 1 }
153
153
  def broadcast_after_to(*streamables, target:, **rendering)
154
- Turbo::StreamsChannel.broadcast_after_to *streamables, target: target, **broadcast_rendering_with_defaults(rendering)
154
+ Turbo::StreamsChannel.broadcast_after_to(*streamables, target: target, **broadcast_rendering_with_defaults(rendering))
155
155
  end
156
156
 
157
157
  # Append a rendering of this broadcastable model to the target identified by it's dom id passed as <tt>target</tt>
@@ -167,7 +167,7 @@ module Turbo::Broadcastable
167
167
  # clearance.broadcast_append_to examiner.identity, :clearances, target: "clearances",
168
168
  # partial: "clearances/other_partial", locals: { a: 1 }
169
169
  def broadcast_append_to(*streamables, target: broadcast_target_default, **rendering)
170
- Turbo::StreamsChannel.broadcast_append_to *streamables, target: target, **broadcast_rendering_with_defaults(rendering)
170
+ Turbo::StreamsChannel.broadcast_append_to(*streamables, target: target, **broadcast_rendering_with_defaults(rendering))
171
171
  end
172
172
 
173
173
  # Same as <tt>#broadcast_append_to</tt>, but the designated stream is automatically set to the current model.
@@ -188,7 +188,7 @@ module Turbo::Broadcastable
188
188
  # clearance.broadcast_prepend_to examiner.identity, :clearances, target: "clearances",
189
189
  # partial: "clearances/other_partial", locals: { a: 1 }
190
190
  def broadcast_prepend_to(*streamables, target: broadcast_target_default, **rendering)
191
- Turbo::StreamsChannel.broadcast_prepend_to *streamables, target: target, **broadcast_rendering_with_defaults(rendering)
191
+ Turbo::StreamsChannel.broadcast_prepend_to(*streamables, target: target, **broadcast_rendering_with_defaults(rendering))
192
192
  end
193
193
 
194
194
  # Same as <tt>#broadcast_prepend_to</tt>, but the designated stream is automatically set to the current model.
@@ -213,7 +213,7 @@ module Turbo::Broadcastable
213
213
 
214
214
  # Same as <tt>broadcast_replace_to</tt> but run asynchronously via a <tt>Turbo::Streams::BroadcastJob</tt>.
215
215
  def broadcast_replace_later_to(*streamables, **rendering)
216
- Turbo::StreamsChannel.broadcast_replace_later_to *streamables, target: self, **broadcast_rendering_with_defaults(rendering)
216
+ Turbo::StreamsChannel.broadcast_replace_later_to(*streamables, target: self, **broadcast_rendering_with_defaults(rendering))
217
217
  end
218
218
 
219
219
  # Same as <tt>#broadcast_replace_later_to</tt>, but the designated stream is automatically set to the current model.
@@ -223,7 +223,7 @@ module Turbo::Broadcastable
223
223
 
224
224
  # Same as <tt>broadcast_update_to</tt> but run asynchronously via a <tt>Turbo::Streams::BroadcastJob</tt>.
225
225
  def broadcast_update_later_to(*streamables, **rendering)
226
- Turbo::StreamsChannel.broadcast_update_later_to *streamables, target: self, **broadcast_rendering_with_defaults(rendering)
226
+ Turbo::StreamsChannel.broadcast_update_later_to(*streamables, target: self, **broadcast_rendering_with_defaults(rendering))
227
227
  end
228
228
 
229
229
  # Same as <tt>#broadcast_update_later_to</tt>, but the designated stream is automatically set to the current model.
@@ -233,7 +233,7 @@ module Turbo::Broadcastable
233
233
 
234
234
  # Same as <tt>broadcast_append_to</tt> but run asynchronously via a <tt>Turbo::Streams::BroadcastJob</tt>.
235
235
  def broadcast_append_later_to(*streamables, target: broadcast_target_default, **rendering)
236
- Turbo::StreamsChannel.broadcast_append_later_to *streamables, target: target, **broadcast_rendering_with_defaults(rendering)
236
+ Turbo::StreamsChannel.broadcast_append_later_to(*streamables, target: target, **broadcast_rendering_with_defaults(rendering))
237
237
  end
238
238
 
239
239
  # Same as <tt>#broadcast_append_later_to</tt>, but the designated stream is automatically set to the current model.
@@ -243,7 +243,7 @@ module Turbo::Broadcastable
243
243
 
244
244
  # Same as <tt>broadcast_prepend_to</tt> but run asynchronously via a <tt>Turbo::Streams::BroadcastJob</tt>.
245
245
  def broadcast_prepend_later_to(*streamables, target: broadcast_target_default, **rendering)
246
- Turbo::StreamsChannel.broadcast_prepend_later_to *streamables, target: target, **broadcast_rendering_with_defaults(rendering)
246
+ Turbo::StreamsChannel.broadcast_prepend_later_to(*streamables, target: target, **broadcast_rendering_with_defaults(rendering))
247
247
  end
248
248
 
249
249
  # Same as <tt>#broadcast_prepend_later_to</tt>, but the designated stream is automatically set to the current model.
@@ -283,7 +283,7 @@ module Turbo::Broadcastable
283
283
  # Same as <tt>broadcast_render_later</tt> but run with the added option of naming the stream using the passed
284
284
  # <tt>streamables</tt>.
285
285
  def broadcast_render_later_to(*streamables, **rendering)
286
- Turbo::StreamsChannel.broadcast_render_later_to *streamables, **broadcast_rendering_with_defaults(rendering)
286
+ Turbo::StreamsChannel.broadcast_render_later_to(*streamables, **broadcast_rendering_with_defaults(rendering))
287
287
  end
288
288
 
289
289
 
@@ -1,6 +1,16 @@
1
1
  if (cable_config_path = Rails.root.join("config/cable.yml")).exist?
2
2
  say "Enable redis in bundle"
3
- uncomment_lines "Gemfile", %(gem 'redis')
3
+
4
+ gemfile_content = File.read(Rails.root.join("Gemfile"))
5
+ pattern = /gem ['"]redis['"]/
6
+
7
+ if gemfile_content.match?(pattern)
8
+ uncomment_lines "Gemfile", pattern
9
+ else
10
+ gem 'redis', '~> 4.0', comment: "Use Redis as Action Cable adapter instead of default Async. The Async adapter\ndoes not support Turbo Stream broadcasting."
11
+ end
12
+
13
+ run_bundle
4
14
 
5
15
  say "Switch development cable to use redis"
6
16
  gsub_file cable_config_path.to_s, /development:\n\s+adapter: async/, "development:\n adapter: redis\n url: redis://localhost:6379/1"
@@ -1,9 +1,9 @@
1
1
  def run_turbo_install_template(path)
2
- system "#{RbConfig.ruby} ./bin/rails app:template LOCATION=#{File.expand_path("../install/#{path}.rb", __dir__)}"
2
+ system "#{RbConfig.ruby} ./bin/rails app:template LOCATION=#{File.expand_path("../install/#{path}.rb", __dir__)}"
3
3
  end
4
4
 
5
5
  def redis_installed?
6
- system('which redis-server')
6
+ system('which redis-server > /dev/null')
7
7
  end
8
8
 
9
9
  def switch_on_redis_if_available
data/lib/turbo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Turbo
2
- VERSION = "0.7.11"
2
+ VERSION = "0.7.15"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: turbo-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.11
4
+ version: 0.7.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Stephenson
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2021-09-03 00:00:00.000000000 Z
13
+ date: 2021-09-23 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rails