Daveyon Mayne 😻
Posted on July 8, 2023
It's never a good idea for partials to reference a global variable, such variable would be current_user
. DHH mentioned this already and I'll show you how to gain access to the current user's information. I do it by storing information of the current_user
in a meta
:
<head>
<meta name="current_user" content="<%= current_user.json_info %>">
</head>
json_info
would contain the information that you need:
# user.rb
[..]
def json_info
{
id: self.id,
name: <NAME>,
# Maybe full url to their avatar?
avatar_url: Rails.application.routes.url_helpers.rails_blob_path(self.avatar, only_path: true)
}.to_json
end
Basic stuff. With that, our current_user
object lives inside the meta
of the document head
.
This partial will be a Stimulus controller and our partial is called _message.html.erb
that lives inside the shared
folder:
<article
data-controller="message"
id="<%= dom_id(message) %>"
data-author-id="<%= message.user.id %>">
<%= message.body %>
</article>
Notice I have here data-author-id
, very important, and I've connected a Stimulus controller. Every time this partial get's rendered in the DOM, the connect
function gets triggered:
// message_controller.js
import { Controller } from '@hotwired/stimulus'
export default class extends Controller {
connect() {
const currentUserBlob = this._getMetaValue('current_user');
const id = JSON.parse(currentUserBlob).id
const authorId = this.element.getAttribute('data-author-id')
// Do something when authorId matches/does not match id.
// This could be hiding/removing an element or something else.
}
_getMetaValue = (name) => {
const element = document.head.querySelector(`meta[name="${name}"]`)
return element?.getAttribute("content")
}
}
Our message model message.rb
would look something like this:
[..]
belongs_to :user
belongs_to :message_thread
has_rich_text :body
after_create_commit do
# We cannot pass current user
broadcast_append_to(self.message_thread, target: self.message_thread, partial: "shared/message", locals: { message: self })
end
message.rb
is just an high-level example showing only the message object that was passed in and nothing else. Depending on what you're doing with "current_user", you'd implement that logic in the Stimulus controller's connect function.
The entire page may look like this:
<%= turbo_stream_from @thread %>
<section id="<%= dom_id(@thread) %>">
<% @messages.each do |message|
<%= render "shared/message", message: message %>
<% end %>
</section>
As a rule of thumb, partials should be free from global references/objects but where a partial is used with ApplicationRenderer, you must connect it with a Stimulus controller to gain access to the current_user
.
🎉 Self-promotion 🎉
I'm building Farm Swop, a platform for farmers where farmers can connect with nearby farmers to share/exchange support, machinery etc. It's in active development. Feel free to join to see my progress while I BuildInPublic.
Photo by Jill Heyer on Unsplash
Posted on July 8, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.