Rails link_to and nested data attributes
The link_to
helper in Rails creates an anchor element, the <a>
tag. It accepts an optional block and three parameters: the name of the link, an options hash, and an HTML options hash.
In Turbo, adding data-turbo-confirm
to the helper can be used to request confirmation from the user before submitting a form. This presents a native browser confirm()
dialog before deleting the blog post.
Here’s how you could prompt the user before deleting a blog post:
<%= link_to "Delete post", post_url(@post),
class: "btn btn-outline-primary",
"data-turbo_method": "delete",
"data-turbo-confirm": "You sure?" %>
As I was writing the Strada chapter for my upcoming book on Turbo Native I stumbled across something exciting. I needed to write a fairly complex link_to
component that had multiple, nested Strada attributes.
I discovered that there’s a more Ruby-friendly way to write data attributes. And in my opinion, the approach is a bit cleaner and easier to read.
Dashes are great but they require wrapping the key in quotes, as shown above. Ideally, we would be able to use underscores, like so:
<%= link_to "Delete post", post_url(@post),
class: "btn btn-outline-primary",
data_turbo_method: "delete",
data_turbo_confirm: "You sure?" %>
Unfortunately, underscores won’t work with Turbo and don’t generate the same HTML output.
<a class="btn btn-outline-primary"
data_turbo_method="delete"
data_turbo_confirm="You sure?"
href="#">Underscores</a>
But what if we nest the data
attributes as a hash?
<%= link_to "Delete post", post_url(@post),
class: "btn btn-outline-primary", data: {
turbo_method: "delete",
turbo_confirm: "You sure?"
} %>
This produces the same output as our first example, data-turbo-method
and data-turbo-confirm
. I like this approach better for two reasons:
- Not seeing
data
for every attribute makes it a bit easier to read. - We can still grep for “turbo_method” across our codebase.
But what if we wanted to go… deeper? Let’s see what happens when we nest the turbo
attributes as well.
<%= link_to "Delete post", post_url(@post),
class: "btn btn-outline-primary", data: {
turbo: {
method: "delete",
confirm: "You sure?"
}
} %>
This produces the following HTML:
<a class="btn btn-outline-primary"
data-turbo="{"method":"delete","confirm":"You sure?"}"
href="#">Deeply nested</a>
Oh dear, that certainly didn’t work! It looks like link_to
tried to convert this to JSON and then escape it before writing the HTML. Unfortunately, that won’t work for Turbo or Strada.
For now, I’ll be sticking with a single-level data
hash. What about you? Which approach do you use in your Rails apps?