Eric / Brooklyn

Random 5

Operator as Methods

Web Accounts

Honeypot Bots

Stripe and Tap

Git Save

Whitespace Problems

Ruby Exits

Appending in Javascript

Sendgrid Ban

Clean URLs

Integer Division

Multi-tab Websockets

Bad Content

JS Data Chutzpah

Responsive tables



Emoji Bits


Ruby vs. Ruby

Extending Devise

Rails UJS

ENV Variables

See All

Dynamically Set Rails UJS

Mar 2020

Experimenting with remote: true

For asynchronous Rails on the front-end, we have a nice remote: true helper that we place inside links and forms.

This allows us to respond to requests with javascript - which is helpful if your app has any single-page-application (SPA)-like behaviors.

SPA-like behavior basically means that a user clicks various links and buttons and the site changes its content without changing its URL.

Setting remote: true is static — meaning, true is always true. This post explores potential use cases for setting the boolean value for remote dynamically, by using a helper method.

Example: A Social Network for Cats

On our homepage, we have a list of cats. When you click on a cat’s name, you want to see their picture appear without going to a new page.

The list part of our view might look something like this:

<% @cats.each do |cat| %>
	<%= link_to, cat, remote: true %>
<% end %>

The key ingredient is remote: true which is a Rails helper that renders out to a typical <a> tag with a data-remote: true attribute in our HTML.

This data-remote attribute tells Rails (via Rails Unobtrusive Javascript) to handle this link a bit differently than usual. Instead of redirecting to the link address and loading the associated view, we want to respond with Javascript and stay put.

We’ll put our javascript in a js.erb file that matches the controller action’s name. Our javascript will just replace the main #cat-image element with the clicked cat’s image.


Well, it turns out, we don’t want to show images to anyone, just other cats who have logged in to the site.

Luckily, Devise gives us a few handy helpers we can use in our views and controllers.

Ordinarily, we’d use a Devise helper as a before_action in the cats controller:

class CatsController < ApplicationController

	before_action: :authenticate_user!, only: [:show]

	def show


And our relevant route looks like this:

get "cats/:id", to: "cats#show", as: "cat"

Which means that our earlier link_to:

<%= link_to, cat, remote: true %>

is shorthand for:

<%= link_to, cat_path(cat), remote: true %>

takes us to the show action of the cats controller.


Devise’s authenticate_user! helper is designed to work nicely for HTML requests, so a user will be redirected to the signup/login page if trying to hit a protected route (i.e. stuff that only logged-in users should see)

But we’re using remote: true, so we’re responding with Javascript (not HTML), so Devise is a bit stuck when a redirect is necessary.

We’re at a fork in the road with at least a few options.

Option 1

We change a few Devise configs so that it responds to JS. Or maybe we have to rewrite authenticate_user!. As we go down this path, things start to feel a bit hacky.

Option 2

We wrap the link_tos in a conditional. Something like:

<% if user_signed_in? %>
	<%= link_to, cat, remote: true %>
<% else %>
	<%= link_to, new_user_registration_path %>
<% end %>

This is our first glimpse of user_signed_in? which is what one might guess - a devise helper that returns a boolean answering its own question.

This way, we allow the user to see the cat picture if she’s logged in — otherwise, we provide a regular non-remote link to the sign-up page.

Option 3

This the option we will choose!

Instead of what we saw in Option 2, we have something like this:

<%= link_to, cat, remote: user_signed_in? %>

Instead of having a static boolean for remote, we have a devise helper method. We could use any helper method available to us in our views here, but for this example, we’ll use Devise.

Our CatsController still looks like this:

class CatsController < ApplicationController

	before_action: :authenticate_user!, only: [:show]

	def show


When user_signed_in? == true :

An async request is made, and everything goes smooth. The user is signed in, and authenticate_user! helper doesn’t try to redirect anywhere.

When user_signed_in? == false :

A regular HTML request is made (because remote: false), and Devise is ready for this because of our before_action. It redirects to the signup/login page.

The end

I chose Option 3 because it’s 1 line of code, and doesn’t require tinkering with various configs.

It also raises some interesting possibilities when deciding whether to request something asynchronously depending on the result of a helper method.