GithubHelp home page GithubHelp logo

hotwired / turbo-rails Goto Github PK

View Code? Open in Web Editor NEW
2.0K 2.0K 288.0 1.92 MB

Use Turbo in your Ruby on Rails app

Home Page: https://turbo.hotwired.dev

License: MIT License

Ruby 48.43% JavaScript 48.58% CSS 0.45% HTML 2.44% Shell 0.10%

turbo-rails's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

turbo-rails's Issues

NoMethodError: undefined method `eager_load!' for Hotwire:Module error

Only getting the above error when I try and deploy to production, and works fine in development. It may be something that's conflicting, i've disabled the old turbolinks and UJS import and start, using turbo in the asset pipeline...any clues on where i should start to look to fix this? - turning off eager loading allows the app to launch

`Turbo is not defined` when trying to call `Turbo.visit`

Hey guys,

I have an app with turbo-rails gem and Im *not using webpack.
On application.html layout I have:

<%= turbo_include_tags %>
<%= stimulus_include_tags %>

but when trying to call Turbo inside stimulus controller (or on browser console) I got the error:
Turbo is not defined

I saw that on response its export { turbo_es2017Esm as Turbo, cable }; but since Im not using webpack I dont think its going to be exported to window object ?

Thanks

Installing `turbo-rails` in existing rails app

I tried to install hotwire-rails in a fresh Rails 6.0.3 application and follow the screencast steps one by one.

I run rails hotwire:install worked as supposed to. The path it followed was the webpacker one as defined in lib/install/turbo_with_webpacker.rb.

However, for some reason, the turbo-frame auto-append behaviour after creating a message was missing, I had to reload the page to see the new message in the page. After some investigation, I realised that the <%= turbo_include_tags %> clause was missing from application.html.erb. By adding the clause, everything works as expected.

This omission is expected by the code, since it does not add the clause like in lib/install/turbo_with_asset_pipeline.rb.

Am I missing something? Is the webpacker path supposed to work without adding the <%= turbo_include_tags %> clause manually?

I would be happy to open a PR, to either update documentation or fix the installation process.

Thoughts?

broadcasts_to does not read broadcast_target_default

Hi,

This works:

class Post < ApplicationRecord
  belongs_to :room
  after_create_commit -> { broadcast_prepend_to :room }
  def broadcast_target_default
    "#{model_name.plural}_#{self.priority}"
  end
end

This doesn't:

class Post < ApplicationRecord
  belongs_to :room
  broadcasts_to :room
  def broadcast_target_default
    "#{model_name.plural}_#{self.priority}"
  end
end

Probably cause https://github.com/hotwired/turbo-rails/blob/main/app/models/concerns/turbo/broadcastable.rb#L61 is init to model_name.plural.

I would expect same behavior and both methods to read broadcast_target_default. Hope this make sense !

Regards

bin/rails zeitwerk:check displays deprecation warning on Rails 6.0.3.4

DEPRECATION WARNING: Initialization autoloaded the constants Turbo::Streams, Turbo::Streams::TurboStreamsTagBuilder, Turbo::Frames, Turbo::Frames::FrameRequest, Turbo::Native, Turbo::Native::Navigation, Turbo::DriveHelper, Turbo::FramesHelper, Turbo::IncludesHelper, Turbo::StreamsHelper, Turbo::Streams::ActionHelper, and Turbo::Broadcastable.

Being able to do this is deprecated. Autoloading during initialization is going
to be an error condition in future versions of Rails.

Reloading does not reboot the application, and therefore code executed during
initialization does not run again. So, if you reload Turbo::Streams, for example,
the expected changes won't be reflected in that stale Module object.

These autoloaded constants have been unloaded.

Please, check the "Autoloading and Reloading Constants" guide for solutions.
 (called from <top (required)> at /config/environment.rb:7)
Hold on, I am eager loading the application.
rails aborted!

Action Text issue with Turbo

Hi hope you're having a good day.

So i have updated my dependies to run Hotwire and replaced the old turbolinks with turbo and since the the Rails Action text trix-editor isnot appearing on the UI i get an empty container.

here is the code for rendering a form


      <%= form_for [current_user, @project, @todolist], html: {class: "w-full"} do |f| %>
      <%= hidden_field_tag :parent_id, current_user.id %>
      <%= hidden_field_tag :project_id, @project.id %>
      <%= f.text_field :name, class: "text--darker font-medium w-full border-b border-transparent placeholder-gray-600 pb-1 focus:outline-none focus:border-gray-500 my-2" , placeholder: "Type the name here"%>
      <section class="hidden" data-todos-target="description">
        <%= f.rich_text_area :description, class: "w-full my-2" %>
      </section>

image

and i get this error in the console
image

this is the content of app/javascript/packs/application.js file

// require("@rails/ujs").start()
// require("turbolinks").start()
require("@rails/activestorage").start()
require("channels")
require("trix")
require("@rails/actiontext");

import "css/application.scss"

import "controllers"
import { Turbo, cable } from "@hotwired/turbo-rails"

Thank you for your time

Cant import Turbo on rails asset pipeline

Importing with ESM doesn't seem to work with the rails asset pipeline

The following throws an error about the package not being found

import { Turbo } from 'turbo'

I set up a rails app with the --skip-javascript option and ran rails turbo:install

Importing stimulus works but I cant seem to import turbo.

I also tried this package name which also doesn't work

import { Turbo, cable } from "@hotwired/turbo-rails"

Am I missing something?

Helpers autoloading

Hi,

I had to do

module ApplicationHelper
  # Should be autoloaded..
  include Turbo::StreamsHelper
  include Turbo::FramesHelper
  ...
end

because i was hitting those errors:

undefined method `turbo_stream_from' for #<ActionView::Base:0x0000000004fab0>
undefined method `turbo_frame_tag' for #<ActionView::Base:0x0000000004e700>

I would expect those to be auto-loaded ?

Specs

Rails 6.1.0

Gemfile.lock

hotwire-rails (0.1.2)
  rails (>= 6.0.0)
  stimulus-rails
  turbo-rails
turbo-rails (0.5.2)
  rails (>= 6.0.0)

Regards

Strange behavior rendering partial from within turbo_stream template

I'm seeing strange behavior when rendering a partial from a turbo stream response.

This example almost directly mirrors the use case documented in the #turbo_stream method of app/helpers/turbo/streams_helper.rb.

I'm using haml in my project, but have tried transitioning everything to erb and still receive the same error.

I've got a controller that attempts to create a thing, and responds to turbo_stream or html formats.

# organization/scheduled_schedule_items_controller
def create
  @scheduled_schedule_item = @schedule.scheduled_schedule_items
    .build(scheduled_schedule_item_params)

  @scheduled_schedule_item.save

  respond_to do |format|
    format.turbo_stream
    format.html { redirect_to schedule_organization_schedule_path(@schedule) }
  end
end

I've got a create.turbo_stream.haml template that is attempting to render a partial.

- # organization/scheduled_schedule_items/create.turbo_stream.haml
- date = @scheduled_schedule_item.item_start_date_as_date

= turbo_stream.replace "schedule-item-modal-form-for-#{date}" do
  - if @scheduled_schedule_item.persisted?
    %p.text-success Success!
  
  - else
    = render 'modal_form', schedule: @schedule, schedule_item: @scheduled_schedule_item, date: date

I receive the following error that the partial (Which is definitely in the right place) can't be found. Seemingly because :formats only include [:turbo_stream].

ActionView::Template::Error (Missing partial organization/scheduled_schedule_items/_modal_form, organization/base/_modal_form, application/_modal_form with {:locale=>[:en], :formats=>[:turbo_stream], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby, :haml, :jbuilder]}. Searched in:
  * "/app/app/views"
  * "/usr/local/bundle/gems/actiontext-6.1.1/app/views"
  * "/usr/local/bundle/gems/actionmailbox-6.1.1/app/views"
):
     5:     <p class="text-success">Success!</p>
     6:   
     7:   <% else %>
     8:     <%= render 'modal_form', schedule: @schedule, schedule_item: @scheduled_schedule_item, date: date %>
     9: 
    10:   <% end %>
    11: <% end %>

If I change the format of my partial render to the below, everything works.

- # organization/scheduled_schedule_items/create.turbo_stream.haml

= render partial: 'modal_form', formats: [:html], locals: { schedule: @schedule, schedule_item: @scheduled_schedule_item, date: date }

This seems out of the ordinary for two reasons:

  1. The example given in the documentation of the #turbo_stream method renders a partial in its response and doesn't explicitly need to include this formats: [:html] bit.
  2. In the old way of doing things, a create.js.erb template would have no issue rendering a .haml or .html.erb partial using something like <%=j render 'form' %>.

Am I missing something obvious here? Thank you.

Possible install instruction change needed for Webpacker 6

I was trying to run the install instructions against the Webpacker 6 beta.

Taking my example which already worked against Webpacker 5, and upgrading Webpacker, my Turbo install was no longer downloading. (The links that had been identified in the log as being processed as TURBO_STREAM no longer were, the behavior was no longer working, and Turbo was no longer in the sources tab).

Adding a console.log(Turbo) to the application.js file makes everything work again, so I guess I'd assume that the switch to Webpacker 6 and the javascript_packs_with_chunks_tag helper somehow doesn't realize that Turbo is being used and therefore doesn't download it with the pack?

Is there a preferred way of managing this?

Thanks!

Syntax for returning multiple turbo streams

Through trial and error I realised that a controller action can return multiple turbo streams. An example would be if you want to append an item to a list, and also show an alert that the item was created.

The syntax is a bit funky if you do it through a controller:

respond_to do |format|
  format.turbo_stream do
    render turbo_stream: [
      turbo_stream.replace(:flash, partial: "layouts/flash", locals: { notice: "Message posted!" }),
      turbo_stream.append(:messages, partial: "messages/message", locals: { message: message })
    ]
  end
end

(you could also do it through a .turbo_stream.erb file, but I like having this in the controller)

Questions:

  1. Should this be documented? If yes, I can make a PR to add it to https://github.com/hotwired/turbo-site/blob/main/docs/handbook/04_streams.md
  2. Would you be open to a neater syntax? I would love to be able to chain turbo streams, like this:
respond_to do |format|
  format.turbo_stream do
    render turbo_stream: turbo_stream
                              .replace(:flash, partial: "layouts/flash", locals: { notice: "Message posted!" })
                              .append(:messages, partial: "messages/message", locals: { message: message })
  end
end

Link_to with method: :post redirects

Just found these:

  • If we use the link_to tag with method: :post it redirects instead of rendering inside the turbo_frame (get works fine)
    whereas `button_to' displays usual behaviour by rendering it inside the turbo_frame

  • link_to...do always redirects to a new page

Are these the usual behaviors, I'm totally new, watching a lot of tutorials here

Turbo is not backwards compatible with Turbolinks

I think it's a bit misleading that there is no information about how Turbo is and isn't backwards compatible with Turbolinks since installing Turbo removes Turbolinks. I'm not sure if the final release version is planned to be backwards compatible, but if not, I think a list of things that are not compatible would be very helpful for people upgrading to Turbo.

Links which specify a data-method have that method ignored

Let's say I have the following in a template:

<%= link_to "Sign out", signout_path, method: :delete %>

When I click on it, I'll get a routing error that seems to reflect the link having been visited with a GET rather than a DELETE request. I believe that this means that turbo-rails is not picking up on the data-method in the rendered link.

Allow to render stream responses with a layout

It would be fantastic to make render turbo_stream: use an optional layout

This way, we can have global-level stream updates that make sense on every page.

For instance, our layout could look like this :

<% if flash[:success].present? %>
  <%= turbo_stream.replace("flash_success") do %>
    <%= render "flash/success" %>
  <% end %>
<% end>
<%= yield %>

Allowing our controller to use flash regardless of the format and then have the layout pick it up either in the stream or in the template.

WDYT ? Happy to provide a PR

What is the purpose of `Turbo::Native::Navigation`?

Turbo::Native::Navigation's comment says "see the Turbo iOS and Turbo Android projects for details".
https://github.com/hotwired/turbo-rails/blob/v0.5.3/app/controllers/turbo/native/navigation.rb#L1-L3
But I could not find code that handle recede, resume, refresh in turbo-ios or turbo-android.

  • Which part handles the native specific response?
  • What happens to a client if one gets that kind of response?
  • Should a port to another language of turbo-rails include Turbo::Native::Navigation?

Error: Form responses must redirect to another location

After use turbo, got error message Error: Form responses must redirect to another location if submit form fail

post.rb

class Post < ApplicationRecord
  validates :title, presence: true, uniqueness: { case_sensitive: false }
end
  # POST /posts
  # POST /posts.json
  def create
    @post = Post.new(post_params)

    respond_to do |format|
      if @post.save
        format.html { redirect_to @post, notice: 'Post was successfully created.' }
        format.json { render :show, status: :created, location: @post }
      else
        format.html { render :new }
        format.json { render json: @post.errors, status: :unprocessable_entity }
      end
    end
  end
<h1>New Post</h1>

<%= render 'form', post: @post %>

<%= link_to 'Back', posts_path %>

WX20201223-014812@2x

Create Webpacker specific installer

The turbo:install command was designed for the asset pipeline. Let's create two new commands: turbo:install:asset_pipeline and turbo:install:webpacker. Then we'll make turbo:install delegate to the right one, depending on whether Webpacker is active in the app.

The turbo:install:webpacker command should make the following changes:

  1. Remove turbolinks and @rails/ujs from the package.json
  2. Remove those libraries from the default application.js pack
  3. Include @hotwired/turbo-rails as described in the README in the pack file.

ActiveStorage uses example.org as host when replaced by a stream

While I am porting my application to Turbo, I run into an issue.

This is the code I've got so far:

The .erb template:

<%= turbo_frame_tag dom_id(vehicle) do %>
  <%= turbo_stream_from vehicle %>
  ... some template code ...
  <%= image_tag vehicle.image.variant(resize_to_fill: [424, 220]) %>
  <% end %>
<% end %>

In my model:

  after_update_commit :broadcast_later

  def broadcast_later
    broadcast_replace partial: "customer/dashboard/vehicle"
  end

This all seems to work great, except for one thing, the image I had in the DOM uses the wrong host after it's being replaced. The initial load uses the right URL, but when it's replaced by a broadcast it changes to example.org.

Before After
image image

I also created this initializer:

ActiveSupport::Reloader.to_prepare do
  ApplicationController.renderer.defaults.merge!(
    http_host: Rails.application.config.action_controller.asset_host
  )
end

I hope you have any idea what the solution could be, thanks!

Webpacker fails compilation with Turbo import.

Hi.

I'm triying to install turbo-rails following the README instructions. I'm using webpacker instead of asset-pipeline.

After install turbo-rails gem and add @hotwired/turbo-rails, when I try to import Turbo and cable in application.js, Webpacker fails compilation with following message:

webpacker | ERROR in ./node_modules/@hotwired/turbo-rails/app/javascript/turbo/index.js 2:9
webpacker | Module parse failed: Unexpected token (2:9)
webpacker | File was processed with these loaders:
webpacker |  * ./node_modules/babel-loader/lib/index.js
webpacker | You may need an additional loader to handle the result of these loaders.
webpacker | | import "./cable_stream_source_element";
webpacker | > export * as Turbo from "@hotwired/turbo";
webpacker | | export * as cable from "./cable";
webpacker | โ„น ๏ฝขwdm๏ฝฃ: Failed to compile.

I tried restarting the server, and re-installing dependencies.

Including `turbo_stream_from` in a partial you're replacing duplicates the element

Not sure how to word this.

If you have a partial:

# _foobar.html.erb
<%= turbo_stream_from model %>

and in a controller action, you're replacing that partial

def do_something
  @model.broadcast_replace partial: "examples/foobar", locals: { model: @model }
end

The turbo-cable-stream-source element will get duplicated exponentially.

IhHIc4cm6v

rails turbo:install fails when application.html.erb is missing

Thor::Error: The file /app/views/layouts/application.html.erb does not appear to exist
/usr/local/bundle/gems/thor-1.0.1/lib/thor/actions/inject_into_file.rb:67:in `invoke!'
/usr/local/bundle/gems/thor-1.0.1/lib/thor/actions.rb:93:in `action'
/usr/local/bundle/gems/thor-1.0.1/lib/thor/actions/inject_into_file.rb:32:in `insert_into_file'
/usr/local/bundle/gems/turbo-rails-0.5.0/lib/install/turbo.rb:2:in `apply'
/usr/local/bundle/gems/thor-1.0.1/lib/thor/actions.rb:227:in `instance_eval'
/usr/local/bundle/gems/thor-1.0.1/lib/thor/actions.rb:227:in `apply'
/usr/local/bundle/gems/railties-6.0.3.4/lib/rails/tasks/framework.rake:15:in `block (2 levels) in <top (required)>'
/usr/local/bundle/gems/appsignal-2.11.1/lib/appsignal/hooks/rake.rb:18:in `execute'
/usr/local/bundle/gems/railties-6.0.3.4/lib/rails/commands/rake/rake_command.rb:23:in `block in perform'
/usr/local/bundle/gems/railties-6.0.3.4/lib/rails/commands/rake/rake_command.rb:20:in `perform'
/usr/local/bundle/gems/railties-6.0.3.4/lib/rails/command.rb:48:in `invoke'
/usr/local/bundle/gems/railties-6.0.3.4/lib/rails/commands.rb:18:in `<top (required)>'
./bin/rails:4:in `require'
./bin/rails:4:in `<main>'
Tasks: TOP => app:template

yarn package 7.0.0-beta.4 not available

Hi,
Is there a version missmatch of turbo and turbo-rails?
I've updated the gem to v0.5.7 however running ./bin/rails turbo:install is not installing the latest version(7.0.0-beta.4) of "@hotwired/turbo-rails" because it is not available yet. https://yarnpkg.com/package/@hotwired/turbo-rails shows that the latest version is 7.0.0-beta.3.
turbo-rails 7.0.0-beta.3. is dependent on "@hotwired/turbo": "^7.0.0-beta.2". With yarn install however @hotwired/turbo": "^7.0.0-beta.3" is installed.

data-disable-with

Hello,

I thought I had read something about data-disable-with related to turbo-rails, but I can't find it in my history anywhere. I notice that data: { disable_with: '...' } doesn't seem to work anymore when making the transition to turbo-rails from turbolinks and rails-ujs.

I wasn't quite sure what made data-disable-with work in the past, but I'm assuming it was rails-ujs since it doesn't seem to be related to turbolinks and the only other thing I removed to make way for turbo-rails was rails-ujs.

Are we planning on having data-disable-with functionality restored? Or is this something we should implement ourselves from here on out?

I've really enjoyed learning about the new magic, thanks for all the efforts!

Devise helper methods and MissingWarden exception

I understand completely it's a way more Devise thing than Basecamp's, but anyway.

Quite simple setup: @posts on the page, form for adding new posts, a post has likes count (from gem 'acts_as_voteable'). Guests are unable to like posts, so the post partial has user_signed_in? method from Devise. Cable doesn't know anything from Devise, sessions, etc, so it's saying Devise::MissingWarden in Posts#create, and a freshly created post is never broadcasted.

Any ideas how to solve this?

Best.

p.s. Thanks for Hotwire and the team's efforts anyway! Overall, looks and feels just mind-blowing.

Turbo Frame events question

First of all, thanks to all of the developers on this project for this lovely holiday surprise gift.

I am part of a small team of developers and today we were playing with adding some javascript/css that would add some minimal styling of turbo-frames for debugging/learning purposes. This mostly worked well when hooking into a turbo:load event; however, when just a frame was being replaced we found that there was not an event we could handle in order to update an attribute on the frame being used for debugging. Is there a way to hook into the replace event?

Also, I am very excited about the direction of hotwire and would like to contribute in some way that would be helpful while also giving me a better understanding of the internals of the code. What is the best way to get involved at this time?

Awkward behavior around redirects & error codes

I'm trying to Turboify an app which uses Devise.

When I try to sign out, I expect the following to happen.

  1. Turbo sends an xhr request to the appropriate Devise controller.
  2. Devise does its post-logout redirect.
  3. Eventually, the redirect chain resolves to HTML containing the signin page.
  4. That HTML gets returned in the xhr response.
  5. Turbo renders the signin page.

Instead, the following happens:

  1. Turbo sends an xhr request to the appropriate Devise controller.
  2. Devise does its post-logout redirect.
  3. Eventually, the redirect chain resolves to a bare 401, because something is autodetecting the XHR and deciding not to return HTML.
  4. No content gets returned to the XHR response, just an error code.
  5. Turbo doesn't render anything, because it got no HTML.
  6. I click on literally any other link, or reload, or the like.
  7. I am immediately redirected to the sign in page with an error.

For my use case, I can probably fix it by overriding the Devise redirect chain -- it's annoying, but not unsolvable.

However, I can see this kind of interaction being really confusing to a naive user. It doesn't really signal what the issue is, it's just a silent failure.

Turbo can't be disabled for button_to helper

Hello,

I have a button that POSTs to a route in my app:

<%= button_to "/auth/github", data: { turbo: false } do %>
  Sign in with GitHub
<% end %>

I added data-turbo="false" to the button to make sure users are properly redirected to GitHub. But when I click the button, an XHR request is fired off to the endpoint with turbo being shown as the initiator.

I tried adding data-turbo="false" to the button's parent element to see if that would fix it, but that's not the case either.

When I remove <%= turbo_include_tags %> from my layout, everything works as expected.

Maybe I am missing something obvious, but not being able to disable Turbo for the button feels like a bug to me.

Tested with:

  • Rails 6.1.0
  • turbo-rails 0.5.1

Happy to provide more information or context if that would be helpful.

Thanks!

Turbo-Rails tries to call `then` on object/string passed to the stream helpers

Rails 6.1.0 installed with rails new --skip-action-mailbox --skip-action-text --skip-active-storage --skip-spring --skip-sprockets. Added gem "turbo-rails", "~> 0.5.1" to the Gemfile and Followed the webpack installation guide.

Any time I call a turbo-stream helper I get:

Screenshot 2020-12-24 at 17 25 47

Same happens in the models when calling:

class Link < ApplicationRecord
  belongs_to :network

  broadcasts_to ->(link) { [ link.network, :links ] }, inserts_by: :prepend, target: "links"
end

It seems some part of the setup is missing, but I can't figure out what yet.

Defined controller layout always gets used

Currently Turbo should be returning responses with layout: false , however I have seen that that if a controller has a defined layout method that the controller defined layout get used in the Turbo response.

eg.

class TestController < ActionController::Base
  def index
  end 
end

Everything will work fine and application.html.erb layout will NOT be used in Turbo response

class TestController < ActionController::Base
  layout "custom"

  def index
  end 
end

custom.html.erb layout will be used for Turbo response and seems to take precendence.

Expectation is that turbo should never use layout in its response

turbo_stream.append "dom_id" says it is required to be wrapped in a template

Hi,

When doing:

<%= turbo_stream.replace "flash_messages" do %>
  <div id="flash_messages">
    <% flash.each do |message_type, message| %>
      <div data-controller="flash-component--base" class="alert alert-<%= alert_class(message_type) %> alert-dismissible fade show" role="alert">
        <%= message %>
        <button
          type="button"
          class="btn-close"
          aria-label="Close"
          data-action="click->flash-component--base#close"></button>
      </div>
    <% end %>
  </div>
<% end %>

Everything works as expected, but when I do:

<%= turbo_stream.append "flash_messages" do %>
  <% flash.each do |message_type, message| %>
    <div data-controller="flash-component--base" class="alert alert-<%= alert_class(message_type) %> alert-dismissible fade show" role="alert">
      <%= message %>
      <button
        type="button"
        class="btn-close"
        aria-label="Close"
        data-action="click->flash-component--base#close"></button>
    </div>
  <% end %>
<% end %>

I get the following javascript error Error: <turbo-stream action="append" target="flash_messages">: first child element must be a <template> element.

If I then wrap it in a template tag, it adds it to the dom like:

<div id="flash_messages">
  <template>
  </template>
</div>

Now, if I use plain html tags and not the rails helpers like below, everything works as expected:

<turbo-stream action="append" target="flash_messages">
  <template>
    <% flash.each do |message_type, message| %>
      <div data-controller="flash-component--base" class="alert alert-<%= alert_class(message_type) %> alert-dismissible fade show" role="alert">
        <%= message %>
        <button
          type="button"
          class="btn-close"
          aria-label="Close"
          data-action="click->flash-component--base#close"></button>
      </div>
    <% end %>
  </template>
</turbo-stream>

I am using:

gem "turbo-rails", "~> 0.5.2"
"@hotwired/turbo-rails": "^7.0.0-beta.2"

ActionCable required even when not using streams

After switching to production I was required to include Action Cable because this gem's app/channels/turbo/streams_channel.rb depends on it.

I am not using streams at all, so I'm wondering if this dependency is avoidable?

TS7016: Could not find a declaration file for module '@hotwired/turbo-rails'

Ran into this error while upgrading a Rails 6 app that uses TypeScript and Turbolinks to the new Turbo. Any ideas? No results on DefinitelyTyped yet.

ERROR in app/javascript/packs/application.ts:10:30
TS7016: Could not find a declaration file for module '@hotwired/turbo-rails'. '/myapp/node_modules/@hotwired/turbo-rails/app/assets/javascripts/turbo.js' implicitly has an 'any' type.
Try `npm i --save-dev @types/hotwired__turbo-rails` if it exists or add a new declaration (.d.ts) file containing `declare module '@hotwired/turbo-rails';`
  8 | 
> 9 | import { Turbo, cable } from "@hotwired/turbo-rails";

Initializer crashes if asset pipeline is not used

If the application does not use the asset pipeline, the app will crash because of the following initializer :

    initializer "turbo.assets" do
      Rails.application.config.assets.precompile += %w( turbo )
    end

undefined method `assets' for #Rails::Application::Configuration:0x00007fa70a4d6be8 (NoMethodError)

Happy to provide a pull request to fix this behaviour if you believe it should not crash in this case

Thanks for making this ! <3

ActiveJob and ActionCable optional loading

I don't use ActionCable or ActiveJob in my application. Also, I don't need real-time updates via WebSocket with Turbo.
If I comment out require "active_job/railtie" and require "action_cable/engine" in my application.rb, I will get the following error when eager loading.

=> Booting Puma
=> Rails 6.1.0 application starting in development
=> Run `bin/rails server --help` for more startup options
Exiting
/home/kazuki/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/turbo-rails-0.5.3/app/channels/turbo/streams_channel.rb:7:in `<main>': uninitialized constant ActionCable (NameError)
Did you mean?  Rational
   from /home/kazuki/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.5.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `require'
   from /home/kazuki/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/bootsnap-1.5.1/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:23:in `block in require_with_bootsnap_lfi'

I would like ActiveJob and ActionCable to be loaded only when necessary.

Thanks!

How to access global `Turbo` object?

In installed by following the readme for an app using the asset pipeline (the install script adds <%= turbo_include_tags %> in my head element).

But because that helper adds the turbo script as a module, the Turbo object isn't added to the global scope (and I can't do Turbo.visit programmatically). Am I missing something? What's the right way of accessing the Turbo object?

Turbo Stream Partial Error handling Question

This is a very specific edge case me and a coworker ran into.

What is the best practice for error handling when broadcasting a turbo stream partial that contains an error?

First off, the simple solution is just to remove errors from your partials. But in a controller, I can also use the following method to render a custom error template. (say maybe render a turbo-frame="_top" to replace the page with a 500 page).

rescue_from ActionView::Template::Error, with: :render_template_error

But in a model that reuses those partials and broadcasts them, when trying to broadcast the partial, the partial throws an error and I now want the page to show the 500 page. Is there a broadcast_to "mychannel", on_error: :render_template_error? And if that is the case, does this start to mix controller logic with model logic? Part of me feels like we should be able to broadcast controller actions.

turbo_stream.remove not removing entity

I'm trying to get started with turbo-rails. I am attempting to create a small sample application and ran into a problem, I can't seem to get turbo_stream.remove to actually remove an item from my html.

The key bits are below

I have the following in my index.html.erb:

<div id="users">
  <%= render @users %>
</div>

the user (_user.html.erb) partial looks like this:

<%= turbo_frame_tag dom_id(user) do %>
  <p data-controller="users">
    <strong>Username:</strong>
    <%= user.username %>

    <input data-users-target="id" value="<%= user.id %>" type="hidden" >
    <%= link_to 'Edit', edit_user_path(user) %> |
    <%= link_to 'Delete', "#", data: { action: "click->users#destroy" } %>
  </p>
<% end %>

Because turbo-rails doesn't currently support data-method, I have the following piece of code in my stimulus controller to handle the delete link:

destroy() {
    const token = document.querySelector('[name=csrf-token]').content

    fetch('/users/' + this.idTarget.value, {
      method: 'DELETE',
      headers: {
        'X-Csrf-Token': token,
        "Accept": "text/html; turbo-stream, text/html, application/xhtml+xml",
        "Turbo-Frame": "users"
      }
    })
  }

My destroy action looks like this:

  def destroy
    @user.destroy
    respond_to do |format|
      format.turbo_stream
      format.html { redirect_to users_url, notice: 'User was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

and my destroy.turbo_stream.erb looks like this

<%= turbo_stream.remove @user %>

I can see that the turbo_stream template gets rendered when the DELETE call is made by looking at the rails server logs, but but the html is never updated, and I can't quite understand what I'm missing (or maybe this use case isn't supported).

Another curious bit is that if I look at the network tab, the request returns a 200 but the response body is blank for the call. If I follow the request through rack and rails middleware, I can see the body being set correctly, so I have no idea where it is getting dropped.

Should this work? Or have I missed something completely obvious?

Here is a link to the example app if that would be helpful: https://github.com/tgturner/diceroll

Response fails to render (client-side) if view files don't contain `.html` in the name

We have a relatively large Rails codebase that uses the slim templating language along with Turbolinks (including native Turbolinks wrappers for iOS and Android). In general, it has worked great for us for years! (Thanks!)

But when I upgraded to Turbo, all our links appeared to stop working: The URL would change, and the client would make the request to the server (per browser console), and the server would render a response (per the Rails logs), but the DOM would never be updated with the content rendered by the server.

After a lot of trial and error, I finally figured out why: Our view files are generally named file_name.slim rather than file_name.html.slim. There was one link I could find that did work, and it happened to be one of the few files that included the .html extension in its name.

Using this naming convention for our view files hasn't caused us issues before, so it's technically a regression from Turbolinks 5. I'm not sure if this is a common pattern that could affect lots of people, or if we're the only app doing it and we've been doing it wrong for years.

I figured it was worth posting here to both clarify our upgrade path (should we bite the bullet and do a massive file rename, or will this be treated as a bug to be fixed?) and to save others time if they encounter the same issue.

Module parse failed: Unexpected token (2:9)

When adding turbo-rails to my already existing Rails 6 application (via webpacker, following the steps of the Readme), I get the following JS errors in the console:

Uncaught Error: Module parse failed: Unexpected token (2:9)
File was processed with these loaders:
 * ./node_modules/babel-loader/lib/index.js
You may need an additional loader to handle the result of these loaders.
| import "./cable_stream_source_element";
> export * as Turbo from "@hotwired/turbo";
| export * as cable from "./cable";
    at Object../node_modules/@hotwired/turbo-rails/app/javascript/turbo/index.js (application.js:2)
    at __webpack_require__ (bootstrap:19)
    at Module../app/webpacker/packs/application.js (application.js:1)
    at __webpack_require__ (bootstrap:19)
    at bootstrap:83
    at bootstrap:83

I am quite helpless on what to do with those errors and if they are specific to my application or some general problem within the turbo package.

Still need explicit format html when render partial in turbo stream

rails 6.1.0
turbo-rails 0.5.2

I create a minimal example in https://github.com/chloerei/turbo-stream-partial-example

When respond with:

<%= turbo_stream.append 'messages' do %>
  <%= render partial: 'message', formats: [:html] %>
<% end %>

Everything is ok.

when respond with:

<%= turbo_stream.append 'messages' do %>
  <%= render partial: 'message' %>
<% end %>

Get error:

ActionView::Template::Error (Missing partial home/_message, application/_message with {:locale=>[:en], :formats=>[:turbo_stream], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby, :jbuilder]}. Searched in:
  * "/app/turbo-stream-partial-example/app/views"
  * "/usr/local/bundle/gems/actiontext-6.1.0/app/views"
  * "/usr/local/bundle/gems/actionmailbox-6.1.0/app/views"
):
    1: <%= turbo_stream.append 'messages' do %>
    2:   <%= render partial: 'message' %>
    3: <% end %>

Send locals var to partial

Hi.
I'm trying to send a local variable to my partial when a message creation commit was triggered

  broadcasts_to  ->(message) { :messages }
  after_create_commit :create_messages_view

  private
    def create_messages_view
      broadcast_append_to self, partial: 'messages/message', locals: { cname: "test" }
    end

But the return is:

[ActiveJob] Enqueued Turbo::Streams::ActionBroadcastJob (Job ID: 2fb92542-1e4e-4930-a410-d5c1f30a3fcc) to Async(default) with arguments: "messages", {:action=>:append, :target=>"messages", :locals=>{:message=>#<GlobalID:0x0000000008ab7a18 @uri=#<URI::GID gid://plezorchat/Message/26c4d6d0-c73e-4c8d-9267-e3d4637adef2>>}, :partial=>"messages/message"}

The local variable cname does not reach the partial

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.