turbo-rails 0.7.10 → 0.7.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +2 -5
- data/app/assets/javascripts/turbo.js +33 -20
- data/app/channels/turbo/streams/broadcasts.rb +16 -16
- data/app/helpers/turbo/streams/action_helper.rb +7 -3
- data/app/models/concerns/turbo/broadcastable.rb +12 -12
- data/lib/install/turbo_needs_redis.rb +1 -1
- data/lib/install/turbo_with_importmap.rb +5 -0
- data/lib/install/turbo_with_node.rb +9 -0
- data/lib/tasks/turbo_tasks.rake +9 -7
- data/lib/turbo/version.rb +1 -1
- metadata +4 -4
- data/lib/install/turbo_with_asset_pipeline.rb +0 -18
- data/lib/install/turbo_with_webpacker.rb +0 -5
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: b6feabeb5b9eef2fcc9032b12f9c067a2ec66408b235a02683540d182276d454
         | 
| 4 | 
            +
              data.tar.gz: 4f20ead78ccf0a8005213c864a4e3df0d82081fac933c435d367997eaf7c7d27
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: '015978592c5ca79dfada00ab3fa9ebceeaeb77b180af317fcf50cf29263571863e753499cab48f4baec165e7a37d438acd93b44720e206a654e8bdb644f4bd63'
         | 
| 7 | 
            +
              data.tar.gz: 2c7d3f5a342f8fd9343e494b55079628fc4e4f04e4a6728c2ef0a26e366c1c2802549da294b6025dede18827421ab1b2ac1c6f9464c0a260829a8c03c69f75b6
         | 
    
        data/README.md
    CHANGED
    
    | @@ -50,7 +50,7 @@ The JavaScript for Turbo can either be run through the asset pipeline, which is | |
| 50 50 |  | 
| 51 51 | 
             
            Running `turbo:install` will install through NPM if Webpacker is installed in the application. Otherwise the asset pipeline version is used. To use the asset pipeline version, you must have `importmap-rails` installed first and listed higher in the Gemfile.
         | 
| 52 52 |  | 
| 53 | 
            -
            If you're using  | 
| 53 | 
            +
            If you're using node and need to use the cable consumer, you can import [`cable`](https://github.com/hotwired/turbo-rails/blob/main/app/javascript/turbo/cable.js) (`import { cable } from "@hotwired/turbo-rails"`), but ensure that your application actually *uses* the members it `import`s when using this style (see [turbo-rails#48](https://github.com/hotwired/turbo-rails/issues/48)).
         | 
| 54 54 |  | 
| 55 55 | 
             
            The `Turbo` instance is automatically assigned to `window.Turbo` upon import:
         | 
| 56 56 |  | 
| @@ -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 | 
            -
             | 
| 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 | 
             
                }
         | 
| @@ -326,7 +327,7 @@ function fetchMethodFromString(method) { | |
| 326 327 | 
             
            }
         | 
| 327 328 |  | 
| 328 329 | 
             
            class FetchRequest {
         | 
| 329 | 
            -
              constructor(delegate, method, location, body = new URLSearchParams) {
         | 
| 330 | 
            +
              constructor(delegate, method, location, body = new URLSearchParams, target = null) {
         | 
| 330 331 | 
             
                this.abortController = new AbortController;
         | 
| 331 332 | 
             
                this.resolveRequestPromise = value => {};
         | 
| 332 333 | 
             
                this.delegate = delegate;
         | 
| @@ -338,6 +339,7 @@ class FetchRequest { | |
| 338 339 | 
             
                  this.body = body;
         | 
| 339 340 | 
             
                  this.url = location;
         | 
| 340 341 | 
             
                }
         | 
| 342 | 
            +
                this.target = target;
         | 
| 341 343 | 
             
              }
         | 
| 342 344 | 
             
              get location() {
         | 
| 343 345 | 
             
                return this.url;
         | 
| @@ -375,7 +377,8 @@ class FetchRequest { | |
| 375 377 | 
             
                  cancelable: true,
         | 
| 376 378 | 
             
                  detail: {
         | 
| 377 379 | 
             
                    fetchResponse: fetchResponse
         | 
| 378 | 
            -
                  }
         | 
| 380 | 
            +
                  },
         | 
| 381 | 
            +
                  target: this.target
         | 
| 379 382 | 
             
                });
         | 
| 380 383 | 
             
                if (event.defaultPrevented) {
         | 
| 381 384 | 
             
                  this.delegate.requestPreventedHandlingResponse(this, fetchResponse);
         | 
| @@ -417,7 +420,8 @@ class FetchRequest { | |
| 417 420 | 
             
                    fetchOptions: fetchOptions,
         | 
| 418 421 | 
             
                    url: this.url.href,
         | 
| 419 422 | 
             
                    resume: this.resolveRequestPromise
         | 
| 420 | 
            -
                  }
         | 
| 423 | 
            +
                  },
         | 
| 424 | 
            +
                  target: this.target
         | 
| 421 425 | 
             
                });
         | 
| 422 426 | 
             
                if (event.defaultPrevented) await requestInterception;
         | 
| 423 427 | 
             
              }
         | 
| @@ -538,7 +542,7 @@ class FormSubmission { | |
| 538 542 | 
             
                this.formElement = formElement;
         | 
| 539 543 | 
             
                this.submitter = submitter;
         | 
| 540 544 | 
             
                this.formData = buildFormData(formElement, submitter);
         | 
| 541 | 
            -
                this.fetchRequest = new FetchRequest(this, this.method, this.location, this.body);
         | 
| 545 | 
            +
                this.fetchRequest = new FetchRequest(this, this.method, this.location, this.body, this.formElement);
         | 
| 542 546 | 
             
                this.mustRedirect = mustRedirect;
         | 
| 543 547 | 
             
              }
         | 
| 544 548 | 
             
              get method() {
         | 
| @@ -1173,7 +1177,7 @@ ProgressBar.animationDuration = 300; | |
| 1173 1177 | 
             
            class HeadSnapshot extends Snapshot {
         | 
| 1174 1178 | 
             
              constructor() {
         | 
| 1175 1179 | 
             
                super(...arguments);
         | 
| 1176 | 
            -
                this.detailsByOuterHTML = this.children.filter((element => !elementIsNoscript(element))).reduce(((result, element) => {
         | 
| 1180 | 
            +
                this.detailsByOuterHTML = this.children.filter((element => !elementIsNoscript(element))).map((element => elementWithoutNonce(element))).reduce(((result, element) => {
         | 
| 1177 1181 | 
             
                  const {outerHTML: outerHTML} = element;
         | 
| 1178 1182 | 
             
                  const details = outerHTML in result ? result[outerHTML] : {
         | 
| 1179 1183 | 
             
                    type: elementType(element),
         | 
| @@ -1255,6 +1259,13 @@ function elementIsMetaElementWithName(element, name) { | |
| 1255 1259 | 
             
              return tagName == "meta" && element.getAttribute("name") == name;
         | 
| 1256 1260 | 
             
            }
         | 
| 1257 1261 |  | 
| 1262 | 
            +
            function elementWithoutNonce(element) {
         | 
| 1263 | 
            +
              if (element.hasAttribute("nonce")) {
         | 
| 1264 | 
            +
                element.setAttribute("nonce", "");
         | 
| 1265 | 
            +
              }
         | 
| 1266 | 
            +
              return element;
         | 
| 1267 | 
            +
            }
         | 
| 1268 | 
            +
             | 
| 1258 1269 | 
             
            class PageSnapshot extends Snapshot {
         | 
| 1259 1270 | 
             
              constructor(element, headSnapshot) {
         | 
| 1260 1271 | 
             
                super(element);
         | 
| @@ -1805,18 +1816,18 @@ class FrameRedirector { | |
| 1805 1816 | 
             
                return this.shouldRedirect(element, submitter);
         | 
| 1806 1817 | 
             
              }
         | 
| 1807 1818 | 
             
              formSubmissionIntercepted(element, submitter) {
         | 
| 1808 | 
            -
                const frame = this.findFrameElement(element);
         | 
| 1819 | 
            +
                const frame = this.findFrameElement(element, submitter);
         | 
| 1809 1820 | 
             
                if (frame) {
         | 
| 1810 1821 | 
             
                  frame.removeAttribute("reloadable");
         | 
| 1811 1822 | 
             
                  frame.delegate.formSubmissionIntercepted(element, submitter);
         | 
| 1812 1823 | 
             
                }
         | 
| 1813 1824 | 
             
              }
         | 
| 1814 1825 | 
             
              shouldRedirect(element, submitter) {
         | 
| 1815 | 
            -
                const frame = this.findFrameElement(element);
         | 
| 1826 | 
            +
                const frame = this.findFrameElement(element, submitter);
         | 
| 1816 1827 | 
             
                return frame ? frame != element.closest("turbo-frame") : false;
         | 
| 1817 1828 | 
             
              }
         | 
| 1818 | 
            -
              findFrameElement(element) {
         | 
| 1819 | 
            -
                const id = element.getAttribute("data-turbo-frame");
         | 
| 1829 | 
            +
              findFrameElement(element, submitter) {
         | 
| 1830 | 
            +
                const id = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("data-turbo-frame")) || element.getAttribute("data-turbo-frame");
         | 
| 1820 1831 | 
             
                if (id && id != "_top") {
         | 
| 1821 1832 | 
             
                  const frame = this.element.querySelector(`#${id}:not([disabled])`);
         | 
| 1822 1833 | 
             
                  if (frame instanceof FrameElement) {
         | 
| @@ -2539,12 +2550,13 @@ class Session { | |
| 2539 2550 | 
             
                });
         | 
| 2540 2551 | 
             
              }
         | 
| 2541 2552 | 
             
              convertLinkWithMethodClickToFormSubmission(link) {
         | 
| 2553 | 
            +
                var _a;
         | 
| 2542 2554 | 
             
                const linkMethod = link.getAttribute("data-turbo-method");
         | 
| 2543 2555 | 
             
                if (linkMethod) {
         | 
| 2544 2556 | 
             
                  const form = document.createElement("form");
         | 
| 2545 2557 | 
             
                  form.method = linkMethod;
         | 
| 2546 2558 | 
             
                  form.action = link.getAttribute("href") || "undefined";
         | 
| 2547 | 
            -
                   | 
| 2559 | 
            +
                  (_a = link.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(form, link);
         | 
| 2548 2560 | 
             
                  return dispatch("submit", {
         | 
| 2549 2561 | 
             
                    cancelable: true,
         | 
| 2550 2562 | 
             
                    target: form
         | 
| @@ -2896,7 +2908,7 @@ class FrameController { | |
| 2896 2908 | 
             
                this.reloadable = false;
         | 
| 2897 2909 | 
             
                this.formSubmission = new FormSubmission(this, element, submitter);
         | 
| 2898 2910 | 
             
                if (this.formSubmission.fetchRequest.isIdempotent) {
         | 
| 2899 | 
            -
                  this.navigateFrame(element, this.formSubmission.fetchRequest.url.href);
         | 
| 2911 | 
            +
                  this.navigateFrame(element, this.formSubmission.fetchRequest.url.href, submitter);
         | 
| 2900 2912 | 
             
                } else {
         | 
| 2901 2913 | 
             
                  const {fetchRequest: fetchRequest} = this.formSubmission;
         | 
| 2902 2914 | 
             
                  this.prepareHeadersForRequest(fetchRequest.headers, fetchRequest);
         | 
| @@ -2932,7 +2944,7 @@ class FrameController { | |
| 2932 2944 | 
             
                frame.setAttribute("busy", "");
         | 
| 2933 2945 | 
             
              }
         | 
| 2934 2946 | 
             
              formSubmissionSucceededWithResponse(formSubmission, response) {
         | 
| 2935 | 
            -
                const frame = this.findFrameElement(formSubmission.formElement);
         | 
| 2947 | 
            +
                const frame = this.findFrameElement(formSubmission.formElement, formSubmission.submitter);
         | 
| 2936 2948 | 
             
                frame.delegate.loadResponse(response);
         | 
| 2937 2949 | 
             
              }
         | 
| 2938 2950 | 
             
              formSubmissionFailedWithResponse(formSubmission, fetchResponse) {
         | 
| @@ -2951,7 +2963,7 @@ class FrameController { | |
| 2951 2963 | 
             
              viewRenderedSnapshot(snapshot, isPreview) {}
         | 
| 2952 2964 | 
             
              viewInvalidated() {}
         | 
| 2953 2965 | 
             
              async visit(url) {
         | 
| 2954 | 
            -
                const request = new FetchRequest(this, FetchMethod.get, expandURL(url));
         | 
| 2966 | 
            +
                const request = new FetchRequest(this, FetchMethod.get, expandURL(url), undefined, this.element);
         | 
| 2955 2967 | 
             
                return new Promise((resolve => {
         | 
| 2956 2968 | 
             
                  this.resolveVisitPromise = () => {
         | 
| 2957 2969 | 
             
                    this.resolveVisitPromise = () => {};
         | 
| @@ -2960,13 +2972,14 @@ class FrameController { | |
| 2960 2972 | 
             
                  request.perform();
         | 
| 2961 2973 | 
             
                }));
         | 
| 2962 2974 | 
             
              }
         | 
| 2963 | 
            -
              navigateFrame(element, url) {
         | 
| 2964 | 
            -
                const frame = this.findFrameElement(element);
         | 
| 2975 | 
            +
              navigateFrame(element, url, submitter) {
         | 
| 2976 | 
            +
                const frame = this.findFrameElement(element, submitter);
         | 
| 2977 | 
            +
                frame.setAttribute("reloadable", "");
         | 
| 2965 2978 | 
             
                frame.src = url;
         | 
| 2966 2979 | 
             
              }
         | 
| 2967 | 
            -
              findFrameElement(element) {
         | 
| 2980 | 
            +
              findFrameElement(element, submitter) {
         | 
| 2968 2981 | 
             
                var _a;
         | 
| 2969 | 
            -
                const id = element.getAttribute("data-turbo-frame") || this.element.getAttribute("target");
         | 
| 2982 | 
            +
                const id = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("data-turbo-frame")) || element.getAttribute("data-turbo-frame") || this.element.getAttribute("target");
         | 
| 2970 2983 | 
             
                return (_a = getFrameElementById(id)) !== null && _a !== void 0 ? _a : this.element;
         | 
| 2971 2984 | 
             
              }
         | 
| 2972 2985 | 
             
              async extractForeignFrameElement(container) {
         | 
| @@ -2987,7 +3000,7 @@ class FrameController { | |
| 2987 3000 | 
             
                return new FrameElement;
         | 
| 2988 3001 | 
             
              }
         | 
| 2989 3002 | 
             
              shouldInterceptNavigation(element, submitter) {
         | 
| 2990 | 
            -
                const id = element.getAttribute("data-turbo-frame") || this.element.getAttribute("target");
         | 
| 3003 | 
            +
                const id = (submitter === null || submitter === void 0 ? void 0 : submitter.getAttribute("data-turbo-frame")) || element.getAttribute("data-turbo-frame") || this.element.getAttribute("target");
         | 
| 2991 3004 | 
             
                if (!this.enabled || id == "_top") {
         | 
| 2992 3005 | 
             
                  return false;
         | 
| 2993 3006 | 
             
                }
         | 
| @@ -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 | 
| 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 | 
| 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 | 
| 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 | 
| 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 | 
| 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 | 
| 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 | 
| 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 | 
| 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 | 
| 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 | 
| 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 | 
| 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 | 
| 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 | 
| 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 | 
| 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 | 
| 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) | 
| 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 | 
| 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 | 
| 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 | 
| 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 | 
| 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 | 
| 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 | 
| 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 | 
| 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 | 
| 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 | 
| 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 | 
| 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 | 
| 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 | 
| 286 | 
            +
                Turbo::StreamsChannel.broadcast_render_later_to(*streamables, **broadcast_rendering_with_defaults(rendering))
         | 
| 287 287 | 
             
              end
         | 
| 288 288 |  | 
| 289 289 |  | 
| @@ -1,6 +1,6 @@ | |
| 1 1 | 
             
            if (cable_config_path = Rails.root.join("config/cable.yml")).exist?
         | 
| 2 2 | 
             
              say "Enable redis in bundle"
         | 
| 3 | 
            -
              uncomment_lines "Gemfile",  | 
| 3 | 
            +
              uncomment_lines "Gemfile", /gem ['"]redis['"]/
         | 
| 4 4 |  | 
| 5 5 | 
             
              say "Switch development cable to use redis"
         | 
| 6 6 | 
             
              gsub_file cable_config_path.to_s, /development:\n\s+adapter: async/, "development:\n  adapter: redis\n  url: redis://localhost:6379/1"
         | 
| @@ -0,0 +1,9 @@ | |
| 1 | 
            +
            if (js_entrypoint_path = Rails.root.join("app/javascript/application.js")).exist?
         | 
| 2 | 
            +
              say "Import Turbo"
         | 
| 3 | 
            +
              append_to_file "app/javascript/application.js", %(import "@hotwired/turbo-rails"\n)
         | 
| 4 | 
            +
            else
         | 
| 5 | 
            +
              say "You must import @hotwired/turbo-rails in your JavaScript entrypoint file", :red
         | 
| 6 | 
            +
            end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            say "Install Turbo"
         | 
| 9 | 
            +
            run "yarn add @hotwired/turbo-rails"
         | 
    
        data/lib/tasks/turbo_tasks.rake
    CHANGED
    
    | @@ -17,23 +17,25 @@ end | |
| 17 17 | 
             
            namespace :turbo do
         | 
| 18 18 | 
             
              desc "Install Turbo into the app"
         | 
| 19 19 | 
             
              task :install do
         | 
| 20 | 
            -
                if  | 
| 21 | 
            -
                  Rake::Task["turbo:install: | 
| 20 | 
            +
                if Rails.root.join("config/importmap.rb").exist?
         | 
| 21 | 
            +
                  Rake::Task["turbo:install:importmap"].invoke
         | 
| 22 | 
            +
                elsif Rails.root.join("package.json").exist?
         | 
| 23 | 
            +
                  Rake::Task["turbo:install:node"].invoke
         | 
| 22 24 | 
             
                else
         | 
| 23 | 
            -
                   | 
| 25 | 
            +
                  puts "You must either be running with node (package.json) or importmap-rails (config/importmap.rb) to use this gem."
         | 
| 24 26 | 
             
                end
         | 
| 25 27 | 
             
              end
         | 
| 26 28 |  | 
| 27 29 | 
             
              namespace :install do
         | 
| 28 30 | 
             
                desc "Install Turbo into the app with asset pipeline"
         | 
| 29 | 
            -
                task : | 
| 30 | 
            -
                  run_turbo_install_template " | 
| 31 | 
            +
                task :importmap do
         | 
| 32 | 
            +
                  run_turbo_install_template "turbo_with_importmap"
         | 
| 31 33 | 
             
                  switch_on_redis_if_available
         | 
| 32 34 | 
             
                end
         | 
| 33 35 |  | 
| 34 36 | 
             
                desc "Install Turbo into the app with webpacker"
         | 
| 35 | 
            -
                task : | 
| 36 | 
            -
                  run_turbo_install_template " | 
| 37 | 
            +
                task :node do
         | 
| 38 | 
            +
                  run_turbo_install_template "turbo_with_node"
         | 
| 37 39 | 
             
                  switch_on_redis_if_available
         | 
| 38 40 | 
             
                end
         | 
| 39 41 |  | 
    
        data/lib/turbo/version.rb
    CHANGED
    
    
    
        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. | 
| 4 | 
            +
              version: 0.7.14
         | 
| 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- | 
| 13 | 
            +
            date: 2021-09-17 00:00:00.000000000 Z
         | 
| 14 14 | 
             
            dependencies:
         | 
| 15 15 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 16 16 | 
             
              name: rails
         | 
| @@ -57,8 +57,8 @@ files: | |
| 57 57 | 
             
            - app/models/turbo/streams/tag_builder.rb
         | 
| 58 58 | 
             
            - config/routes.rb
         | 
| 59 59 | 
             
            - lib/install/turbo_needs_redis.rb
         | 
| 60 | 
            -
            - lib/install/ | 
| 61 | 
            -
            - lib/install/ | 
| 60 | 
            +
            - lib/install/turbo_with_importmap.rb
         | 
| 61 | 
            +
            - lib/install/turbo_with_node.rb
         | 
| 62 62 | 
             
            - lib/tasks/turbo_tasks.rake
         | 
| 63 63 | 
             
            - lib/turbo-rails.rb
         | 
| 64 64 | 
             
            - lib/turbo/engine.rb
         | 
| @@ -1,18 +0,0 @@ | |
| 1 | 
            -
            if (app_js_path = Rails.root.join("app/javascript/application.js")).exist?
         | 
| 2 | 
            -
              say "Import turbo-rails in existing app/javascript/application.js"
         | 
| 3 | 
            -
              append_to_file app_js_path, %(import "@hotwired/turbo-rails"\n)
         | 
| 4 | 
            -
            else
         | 
| 5 | 
            -
              say <<~INSTRUCTIONS, :red
         | 
| 6 | 
            -
                You must import @hotwired/turbo-rails in your application.js.
         | 
| 7 | 
            -
              INSTRUCTIONS
         | 
| 8 | 
            -
            end
         | 
| 9 | 
            -
             | 
| 10 | 
            -
            if (importmap_path = Rails.root.join("config/importmap.rb")).exist?
         | 
| 11 | 
            -
              say "Pin @hotwired/turbo-rails in config/importmap.rb"
         | 
| 12 | 
            -
              append_to_file importmap_path.to_s, %(pin "@hotwired/turbo-rails", to: "turbo.js"\n)
         | 
| 13 | 
            -
            else
         | 
| 14 | 
            -
              say <<~INSTRUCTIONS, :red
         | 
| 15 | 
            -
                You must add @hotwired/turbo-rails to your importmap to reference them via ESM.
         | 
| 16 | 
            -
                Example: pin "@hotwired/turbo-rails", to: "turbo.js"
         | 
| 17 | 
            -
              INSTRUCTIONS
         | 
| 18 | 
            -
            end
         |