I have a Turbo Frame on my page which uses the src
attribute to load in /chats/
. Within this frame I want to be able to know whether the main page is using the show
action of the groups
controller, i.e. the URL of the page is at /groups/group_name
.
Using current_page?(controller: 'groups', action: 'show')
returns false as it sees itself as in the chats
controller. How do I work around this?
Here are the options I've found:
request.referrer
There doesn't appear to be a built-in way of getting to the controller class / action in the way that you're describing, but you can access the URL of the page which initiated the Turbo request (groups_controller#show) through request.referrer
. This will be the fully-qualified URL for the page, such as http://localhost:3000/groups/1/show
.
This requires changes to view code (you must add query params to all links where you need this functionality), but it allows you to pass controller/action names and any other arbitrary data you'd like.
Example:
in application_controller.rb:
# define a method to capture the information you wish to access during your Turbo stream request
def current_route_info
{
path: current_path,
controller: params[:controller],
action: params[:action]
}
end
No need to touch the groups controller in this example.
in show.html.erb (the page which submits the Turbo request)
<%= form_with url: turbo_view_path(info: current_route_info) do %>
...
<% end %>
OR
<%= link_to turbo_view_path(info: current_route_info) do %>
...
<% end %>
OR
<!-- you could also manually build the URL & encode the query params if you need to avoid URL helpers-->
<turbo-frame id="" src=chats_partial_path(info: current_route_info)>
...
<turbo-frame>
chats partial controller (which handles the Turbo request)
def turbo_view_method
params[:info]
# => info as defined in current_route_info
end
flash
I've just learned the many ways you can use flash
for this type of functionality that extends across requests. This is less work than using query parameters, mainly because you don't need to adjust your view code.
Example:
groups controller (which renders the show view, which submits the Turbo requests)
def show
# stick the current controller and action params into flash
# again, you can add any other arbitrary (primitive) data you'd like
flash[:referrer] = params.slice(:controller, :action)
...
...
end
chats partial controller (which handles the Turbo requests)
def chats_turbo_method
flash[:referrer]
# => { controller: "some_controller", action: "show" }
# NOTE: flash will retain this :referrer key for exactly 1 further request.
# If you require this info for multiple Turbo requests,
# you must add:
flash.keep(:referrer)
# and you will have access to flash[:referrer] for as many Turbo requests as you want to make from group#show
end