Hotwire Discussion

Authentication and Devise with broadcasts

What is the equivalent of the Connection class in Rails for Turbo::Stream ?
I want to use an identified_by method with Devise for the streams, but I end up with an error like this:
[Turbo::Streams::ActionBroadcastJob] [1fdec594-eeb2-4a37-94f5-3d7e172ec03f] Error performing Turbo::Streams::ActionBroadcastJob (Job ID: 1fdec594-eeb2-4a37-94f5-3d7e172ec03f) from Async(default) in 6.58ms: ActionView::Template::Error (Devise could not find theWarden::Proxyinstance on your request environment. Make sure that your application is loading Devise and Warden as expected and that theWarden::Manager middleware is present in your middleware stack.

1 Like

Thank you for sending me piece of the source-code. I’m not sure how this solve the issue of broadcasting a partial that contains a current_user set by devise. I guess that it means we could send a partial to a specific user and then again, as long as the partial doesn’t reference a current_user

Partials used for turbo streaming have to be free of global references, as they’re rendered by the ApplicationRenderer, not within the context of a specific request.

2 Likes

So it means there is no way we can access user details (from current_user) in our streams? Is there any workaround?

Use case:

Chat application with messages where sender is specified.

This is how I made it work, essentially by breaking up broadcasts call on the model into individual broadcasts per ActiveRecord action (create, update, destroy) and passing in user as a parameter into the partial: Making Hotwire and Devise play nicely

I’ve tried follow your post.

Making Hotwire and Devise play nicely.

But I still get below error.

NameError - undefined local variable or method `current_user' for #<Chat:0x00007feac3ac0890>:
  app/models/chat.rb:9:in `block in <class:Chat>'
  app/controllers/a/chats_controller.rb:14:in `block in create'
  app/controllers/a/chats_controller.rb:13:in `create'

Do you have a public repository of the post.
I want to see your whole implements.

Unfortunately I don’t have a full repository at the moment but I’m working on it. In the meantime, I’d be happy to look at your code snippet to see if I can find anything.

1 Like

I had a situation whereby (taking the tutorial example) when the current user created a new message I wanted the appended message to render for them with edit / delete actions but not for other users.

The solution I went with was to use a turbo stream to target one div on the current users rendered page and broadcasts to target a different one. e.g.

<% if current_user %>
  <%= turbo_frame_tag "new_message", src: new_room_message_path(@room), target: "_top" %>
  <div id="current_user_messages">
    <%= render @room.messages %>
  </div>
<% else %>
  <%= turbo_stream_from "messages" %>
  <div id="messages">
    <%= render @room.messages %>
  </div>
<% end %>

# create.trubo_stream
<%= turbo_stream.prepend "current_user_messages" do %>
  # so you can use current user logically when rendering template
  <%= render partial: "message", locals: { message: @message current_user: current_user } %>
<% end %>

# message.rb
after_create_commit { broadcast_prepend_to 'messages' }

# messages_controller.rb
...
respond_to do |format|
  format.turbo_stream
end

# _message.html.erb
<%= turbo_frame_tag dom_id(message do %>
   ....
  <% if current_user %>
    <div><%= link_to 'Edit'...></div>%>
  <% end %>
<% end %>