Blog

Thoughts from my daily grind

Rails UJS Trigger Second Remote Route from Within One

Posted by Ziyan Junaideen |Published: 13 March 2021 |Category: Code
Default Upload |

Rails is a mature framework with its own set of opinions, we call it the Rails Way. This just works 80% of the time. There are times you need to break pattern. Some times this is because of limitations. Some times it is because you didn't know better. That is what I spotted today.

I have been supervising a Rails project and reviewing pull-requests made to its Github Repository. One PR caught my eye. There was a rendering of one view from within another. I am not talking about partials, but full views. I looked in the code, understood what he wanted to do, and got the dev on chat.

The Offence

There are 2 actions; marketing/sessions#new and marketing/orders#new. Both of them are to be called by remote links (remote: true) and are supposed to inject a Bootsrap modal and show it.

If the order is triggered and user is not logged in (it shouldn't happen, but in case) then the login modal should show and do its magic and login the user. To achieve this he rendered the marketing/sessions/new.js.erb file from within marketing/orders/new.js.erb and altered views to get it to work.

<% if current_user %>
  // ...
<% else %>
  <%= render(template: 'marketing/sessions/new') %>
<% end %>

The Problems

Keep aside the WTF moment I had, there are few concerns I have with this approach. You can get it to work doesn't mean it is right.

First of all, this violates the Rails way. It's normal to render a partial, not so much for an entire view. There may be edge cases where it is needed, but this is not such a casae.

Secondly the controller action has some analytics logic attached to it. By just rendering the JS view that will not get triggered leading to an inconsistency in data gathered.

Thirdly what could have been a one liner in a single file ended up altering multiple files. This is because when you render a view with the template option, any partials that view use will be searched from within the views directory and not the files particular directory. Thus the PR had many changes that were changing partial rendering to use full paths like render 'modal' => render 'marketing/sessions/modal'.

The Solution

The solution to this problem is simple and I was surprised the developer didn't know it. All you have to do is to make a GET request using jQuery. This is some thing I found out accidentally about 7 years ago.

$.get('<path>', function(_) {}); 

It is that simple. It will call the URL, get the JS response and evaluate it (eval()). You don't have to do any thing else. While I don't use this in person that often, I always thought it was common knowledge. I did some searches, may be its bad keywords, but I didn't get a satisfactory answer to share with the developer. That is why I thought of writing this post. Any ways we can improve the above situation as:

<% if current_user %>
  // ...
<% else %>
  $.get('<%= new_session_path %>', function(_) {});
<% end %>

In case you didn't know, now you know! Happy hacking!

Tags
About the Author

Ziyan Junaideen -

Ziyan is an expert Ruby on Rails web developer with 8 years of experience specializing in SaaS applications. He spends his free time he writes blogs, drawing on his iPad, shoots photos.

Comments