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

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.

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

<div onClick="doClick()">Click me</div>

(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 a 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.

Get the latest Rails Designer updates

Published at . Have suggestions or improvements on this content? Do reach out. Interested in sharing Rails Designer with the Ruby on Rails community? Become an affiliate.

UI components for Ruby on Rails apps

$ 99 69 one-time
payment

Get Access
  • One-time payment

  • Access to the entire library

  • Built for Ruby on Rails

  • Designed with Tailwind CSS and enhanced with Hotwire

  • Includes free updates (to any 1.x version)