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 Rails’ link_to and button_to? 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 an element with say, an inline-form, a button_to is the correct choice.

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

Get UI & Product Engineering Insights for Rails Apps (and product updates!)

Published at . Last updated at . Have suggestions or improvements on this content? Do reach out.

UI components for Ruby on Rails apps

$ 129 one-time
payment

Get Access
  • One-time Payment

  • Access to the Entire Library

  • Built for Ruby on Rails (inc. Rails 8)

  • Designed with Tailwind CSS and Enhanced with Hotwire

  • Updates for 12 months