DEV Community

Rails Designer
Rails Designer

Posted on • Edited on • Originally published at railsdesigner.com

When to use `link_to` and `button_to` in Rails

This article was originally published on Rails Designer


This article about forms inside forms triggered a question from a reader: when to use link_to and button_to in Rails? So I wanted to publish this short and quick article.

Rails has had both helpers from the very early beginnings. link_to likely from the first release, and button_to not much later.

With the release of Rails' ujs, link_to could now accept data-attributes as seen in these older docs. This made many Rails developers belief this the right way to do it, but: you should use link_to for simple navigation and GET requests, and button_to for actions that submit data or require additional security, such as POST, PUT, or DELETE requests.

🎨 Rails Designer is a professionally designed UI components library for Rails. Built with ViewComponent. Designed with Tailwind CSS. Enhanced with Hotwire. Build beautiful, faster.

I've seen some nasty HTML-element abuse in pure JavaScript apps too. Something like this:

<div onClick="doClick()">Click me</div>
Enter fullscreen mode Exit fullscreen mode

(that's like using a spoon to cut your steak—technically possible, but awkwardly ineffective and a nightmare for accessibility!)

  • link_to generates an anchor tag (<a>): link_to "Profile", profile_path(@user), class: "link";
  • button_to generates a form with a single button: button_to "Delete Account", account_path(@user), method: :delete, form: { data: { turbo_confirm: "Are you sure?" } }.

button_to should also, for better accessibility and semantic correctness, be used to open modal or slide-overs. I could present a counterpoint if the modal or slide-over could also be opened as a separate page.

Also when you replace an element with say, an inline-form, a button_to is the correct choice.

It's as simple as that really. Is it GET request and does it change the URL? Go for a link_to. Otherwise choose button_to.

Top comments (0)