Hello!
I am roughly following an example I found here and running into some issues: ChatGPT streaming with ruby-openai, Rails 7, Hotwire, Turbostream, Sidekiq and Tailwind! · GitHub (a major difference is I have a model and controller callled ChatMessage
not just Message
and my Model has a field called message
in place of content
)
I’m currently having an issue where submitting the form causes the browser to redirect to the Turbo stream response (as plain text) instead of placing it in the frame. I think this is because Turbo is not adding text/vnd.turbo-stream.html
to the Accept
request header when submitting the form or it is not interrupting the form/preventing default handling. Rails correctly responds with a text/vnd.turbo-stream.html
response.
I can’t figure out/find documentation for how to really debug or log anything with Turbo in the browser/JavaScript side. I can confirm that Stimulus is working fine elsewhere in my app (so JS is loading), and Turbo-based navigation/redirects between pages (the default functionality from Rails scaffold that doesn’t require additional setup) is working fine.
I have a form that looks like:
<%= turbo_frame_tag "#{dom_id(chat)}_chat_message_form" do %>
<%= form_with(model: ChatMessage.new, url: chat_chat_messages_path(format: :turbo_stream)) do |form| %>
<div class="my-5">
<%= form.text_area :message, rows: 4, class: "block shadow rounded-md border border-gray-200 outline-none px-3 py-2 mt-2 w-full", autofocus: true, "x-on:keydown.cmd.enter" => "$event.target.form.requestSubmit();" %>
</div>
<div class="grid justify-items-end">
<%= form.button type: :submit, class: "rounded-lg py-3 px-5 bg-blue-600 text-white inline-block font-medium cursor-pointer" do %>
<i class="fas fa-paper-plane"></i>
<span class="pl-2">Send</span>
<% end %>
</div>
<% end %>
<% end %>
I needed to change the URL from url: [chat, chat.chat_messages.new]
to chat_chat_messages_path(format: :turbo_stream)
or I would get an ActionController::UnknownFormat
error from Rails.
I tried adding data: {turbo_stream: true}
or data: {turbo_stream: true, turbo_frame: "#{dom_id(chat)}_chat_message_form"}
to the form_with
to no effect.
Rails 7.1.1 turbo-rails 1.5.0 @hotwired/turbo-rails 7.3.0
Controller:
class ChatMessagesController < ApplicationController
include ActionView::RecordIdentifier
before_action :authenticate_user!
def create
@chat_message = ChatMessage.create(chat_message_params.merge(chat: Chat.user_last_chat(current_user), role: "user"))
GetAiResponse.perform_later(@chat_message.chat_id)
respond_to do |format|
format.turbo_stream
end
end
private
def chat_message_params
params.require(:chat_message).permit(:message)
end
end
create.turbo_stream.erb
:
<%= turbo_stream.append "#{dom_id(@chat_message.chat)}_chat_messages" do %>
<%= render "chat_message", chat_message: @chat_message, scroll_to: true %>
<% end %>
<%= turbo_stream.replace "#{dom_id(@chat_message.chat)}_chat_message_form" do %>
<%= render "form", chat: @chat_message.chat %>
<% end %>
routes.rb
:
resource :chat, only: [:create, :new, :current_chat], as: :current_chat do
member do
# Some other paths here as well
resources :chat_messages, only: [:create], as: :chat_chat_messages
end
end
I’m really stumped on this! Any help is much appreciated!