Turbo Stream and Devise current_user

fmartinez fmartinez posted on 2023-11-22 14:25:32 UTC

I want a partial that can access "current_user" from turbo_stream
Turbo_stream is triggered through a commit in the model, and broadcast a partial

Lets say this: 
class Message < ApplicationRecord  
belongs_to :room  
belongs_to :user  
has_one_attached :image
broadcasts_to :room
end


I've read information that people are trying  to 
1) add current_user in the model through Current Attributes (unclear at least for me)
2) variable added in the partial (anyhow, the partial are re-render on each broadcast)
3) add current_user in the DOM

Not sure which path to follow

Anyone have a suggestion?






fmartinez PRO said 6 months ago :
For the 1 and 2, just didn't work due needed the information from the logged in user
Seems to me that turbo streams create the partial to be pasted in the target without any interaction, only the model create the partial with db info
So, no way to get current_user

The only way that worked for me was number 3
Initially I wanted to trigger a stimulus action on turbo load, but, it wasn't enough. 
I think this will require some morph... too much work for a personal project

End up selecting path number 3
Added current user on the DOM
<div hidden id="session_set"><%= current_user.id%></div>

Then, on the partial, added plain javascript code
I just wanted to align according current user, so, I added this on the partial
    <script> 
        if(document.getElementById("session_set").innerHTML == <%= message.user.id %>) {
            let msgPartial = <%="message_#{dom_id message}"%>;
            msgPartial.classList.add("justify-end");

            let msgPartialContainer = <%="message_#{dom_id message}_container"%>;
            msgPartialContainer.classList.add("flex-row-reverse");

            let msgPartialUsertag = <%="message_#{dom_id message}_usertag"%>;
            msgPartialUsertag.classList.add("ml-10");

        }
    </script>

Spend sooooo much time on it that didn't care to go all 90's on it

Im okay with it due its only for presentation purpose
Anyhow for edit or delete action could create a static turbo_stream_from with information of the user that match (is the approach of this video https://www.youtube.com/watch?v=NxlfCYP7Gfo). Anyhow, due it is static, the approach didn't work for me

Well, this is my learning Hotwire experience repo
https://github.com/droidfer/turbochat


David Kimura PRO said 6 months ago :
The issue with devise and broadcasting is warden gets angry. To get around this, I will pass a user object into the partial or use the Current Attributes. You have to be careful with broadcasts and the current user object because all broadcasts will be in the context of that current user. As a workaround, I have broadcasted an empty turbo frame tag with a src attribute which makes a request back to the app to get the actual current user object but depending on your scenario, it would create  a n+1 request situation.

fmartinez PRO said 6 months ago :
I've follow a Current Attribuites tutorial on this forum https://www.driftingruby.com/episodes/current-attributes?query=current+attribuites
My experience with it was that I open 2 browser, register with 2 users... and the last user register was the Current.user for all
I felt that it was a global variable for all users (this is an statement I produce without much knowledge)
Didn't dig much into it due I had other options to explore

I would love to go for a stimulus controller that updates everything once turbo finish render, that will mean morphing (that I think is coming soon for hotwire)
Must add that it made me appreciate a little bit more react once I found this issue

For your workaround... I was trying to do something similar... but... it was so much easier doing with Javascript (plain javascript)
Anyhow, if I do it that way, I will create a partial for broadcast that includes a request back the current user, and, another partial for full page render without that query

Login to Comment
Back to forums