2

In a regular Rails 7 application, if you build an #index action that lists Tweets, and you want the user to be able to edit the tweets inline, you could do something like this:

# _tweet.html.erb
<%= turbo_frame_tag(tweet) do %>
  <%= tweet.text %>
  <%= link_to "Edit this tweet", edit_tweet_path(tweet) %>
<% end %>

And then in tweets/edit.html.erb:

<%= turbo_frame_tag(tweet) do %>
  <%= render "form", tweet: @tweet %>
<% end %>

Even tough it works, I'd like to prevent users from hitting the URL /tweets/1/edit directly, so that the edit.html.erb is only accessible via the Turbo frame request.

However, these edit request (which is not a turbo_stream form submissions) is actually just a regular HTML request (it prints Processing by TweetsController#edit as HTML in the console), so by doing this:

def edit
  respond_to {|format| format.turbo_stream }
end

I can't prevent users from accessing /tweets/1/edit directly, since it's not a turbo stream.

In the good ol days of Rails UJS, this could be easily achieved by restricting the controller to respond to format.js, like so:

def edit
  respond_to {|format| format.js }
end

Or only providing a edit.js.erb file in the views folder, because then HTML requests wouldn't be served if the user requested /tweets/1/edit` directly (as it would be an HTML request).

Any way to achieve the same using Hotwire & Turbo?

sandre89
  • 5,218
  • 2
  • 43
  • 64

2 Answers2

1

First, I’d like to ask why would you want to restrict this? The spirit of turbo, specially frames and drive, is for your app to be progressively enhanced from full page interactions (regular http requests) all the way down to micro interactions like the one you’re mentioning. The problem you’re describing would only present itself if your users used cmd/ctrl + click to open the edit link. Have you actually measured how many people do that? Like, open it in a new tab? Measuring that might get you some idea of how important it’d be to restrict that.

Now, to the specifics of your question.

There isn’t currently (march 2022) a way to detect a turbo frame request and respond differently to it. You could follow this issue and maybe get some answers there: https://github.com/hotwired/turbo-rails/issues/229

My gut feeling though is that what you’re thinking of doing kind of goes against the grain and that it may be an optimisation that’s not really needed.

pinzonjulian
  • 161
  • 1
  • 8
0

You could check for the Turbo-Frame header that is provided by turbo when it fetches frame content. I was looking for a way to determine this so that I didn't need to have to create a separate controller and view for content loaded into the frame via the src attribute.

Screenshot of what the header looks like in Chrome inspector