DEV Community

William Kennedy
William Kennedy

Posted on • Originally published at williamkennedy.ninja on

Rails TIP: Use dom_id to Generate Ids in HTML

alt textPhoto by Pankaj Patel on Unsplash

Overview

When working with Rails, there’s always a better way to do something.

One of my favourite discoveries recently is the dom_id helper, which I discovered while learning about Stimulus Reflex.

It’s one of those tools that I wish I discovered years ago.

If you’ve written code like below, dom_id may help you in the future.

<% @posts.each do |post| %>
  <p id="index_post_<%= post.id %>"></p>
<% end %>

Enter fullscreen mode Exit fullscreen mode

There is nothing wrong here, the issue arises when you have to interact with the dom via Javascript or a background job. Your code ends being a little less dry because you have to remember that you prepended index_post_<%= post.id %> every time.

I have come across code like this in a js.erb template.

var post = document.querySelector("#index_post_<%= @post.id %>")  

Enter fullscreen mode Exit fullscreen mode

And in the background job or service worker, you will also have to remember this format if you plan on using something like cable ready to update the dom.

Luckily, dom_id provided a simple way to clean up all that code and make everything DRYer.

How do you use dom_id?

As with a lot of view helpers in Rails, using it is straightforward.

Using it in a view

Let’s imagine we have a Post model.

The dom_id methods take one argument and one optional argument for a prefix.

# without prefix
dom_id(Post.find(2)) # => "post_2”
dom_id(Post.new) # => "new_post”
# with prefix
dom_id(post.find(2)) #=> “post_2”
dom_id(post.find(2), :custom) #=> “custom_post_2”


Enter fullscreen mode Exit fullscreen mode

Using it from a background job or model

Since dom_id is baked right into Rails, you can call it from anywhere using ActionView.

app/models/post.rb
def dom_id
  ActionView::RecordIdentifier.dom_id(self)
end

Enter fullscreen mode Exit fullscreen mode

Happy coding.

Top comments (0)