turbo-rails 0.7.11 → 0.7.15

Sign up to get free protection for your applications and to get access to all the features.
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