I have 3 models and each model has an index
page that loads all its respective instances lazily with the link to its show
page. Imagine something like this:
On clicking the link of any instance of any model, it makes a couple of requests for the same page & request type:
22:32:33 web.1 | Started GET "/transactions/5709759" for 127.0.0.1 at 2023-11-23 22:32:33 +0530
22:32:33 web.1 | Processing by TransactionsController#show as HTML
22:32:33 web.1 | Parameters: {"id"=>"5709759"}
22:32:33 web.1 | Transaction Load (0.4ms) SELECT "transactions".* FROM "transactions" WHERE "transactions"."slug" = $1 ORDER BY "transactions"."date" DESC LIMIT $2 [["slug", "5709759"], ["LIMIT", 1]]
22:32:33 web.1 | ↳ config/initializers/cancancan.rb:18:in `find'
22:32:33 web.1 | User Load (0.4ms) SELECT "users"."id", "users"."slug" FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 2], ["LIMIT", 1]]
22:32:33 web.1 | ↳ app/controllers/application_controller.rb:19:in `current_user'
22:32:33 web.1 | Thaali Load (1.0ms) SELECT "thaalis".* FROM "thaalis" WHERE "thaalis"."id" = $1 LIMIT $2 [["id", 168], ["LIMIT", 1]]
22:32:33 web.1 | ↳ app/controllers/transactions_controller.rb:18:in `show'
22:32:33 web.1 | Sabeel Load (0.5ms) SELECT "sabeels".* FROM "sabeels" WHERE "sabeels"."id" = $1 LIMIT $2 [["id", 69], ["LIMIT", 1]]
22:32:33 web.1 | ↳ app/controllers/transactions_controller.rb:19:in `show'
22:32:33 web.1 | Rendering layout /usr/share/rvm/gems/ruby-3.2.2/gems/turbo-rails-1.5.0/app/views/layouts/turbo_rails/frame.html.erb
22:32:33 web.1 | Rendering transactions/show.html.erb within layouts/turbo_rails/frame
22:32:33 web.1 | Rendered transactions/_transaction.html.erb (Duration: 0.5ms | Allocations: 143)
22:32:33 web.1 | Rendered shared/_destroy_modal.html.erb (Duration: 0.5ms | Allocations: 126)
22:32:33 web.1 | Rendered shared/_actions.html.erb (Duration: 1.2ms | Allocations: 243)
22:32:33 web.1 | Rendered transactions/show.html.erb within layouts/turbo_rails/frame (Duration: 2.7ms | Allocations: 580)
22:32:33 web.1 | Rendered layout /usr/share/rvm/gems/ruby-3.2.2/gems/turbo-rails-1.5.0/app/views/layouts/turbo_rails/frame.html.erb (Duration: 3.0ms | Allocations: 679)
22:32:33 web.1 | Completed 200 OK in 34ms (Views: 3.9ms | ActiveRecord: 2.3ms | Allocations: 3942)
22:32:33 web.1 |
22:32:33 web.1 |
22:32:33 web.1 | Started GET "/transactions/5709759" for 127.0.0.1 at 2023-11-23 22:32:33 +0530
22:32:33 web.1 | Processing by TransactionsController#show as HTML
22:32:33 web.1 | Parameters: {"id"=>"5709759"}
22:32:33 web.1 | Transaction Load (0.4ms) SELECT "transactions".* FROM "transactions" WHERE "transactions"."slug" = $1 ORDER BY "transactions"."date" DESC LIMIT $2 [["slug", "5709759"], ["LIMIT", 1]]
22:32:33 web.1 | ↳ config/initializers/cancancan.rb:18:in `find'
22:32:33 web.1 | User Load (0.2ms) SELECT "users"."id", "users"."slug" FROM "users" WHERE "users"."id" = $1 LIMIT $2 [["id", 2], ["LIMIT", 1]]
22:32:33 web.1 | ↳ app/controllers/application_controller.rb:19:in `current_user'
22:32:33 web.1 | Thaali Load (0.7ms) SELECT "thaalis".* FROM "thaalis" WHERE "thaalis"."id" = $1 LIMIT $2 [["id", 168], ["LIMIT", 1]]
22:32:33 web.1 | ↳ app/controllers/transactions_controller.rb:18:in `show'
22:32:33 web.1 | Sabeel Load (0.7ms) SELECT "sabeels".* FROM "sabeels" WHERE "sabeels"."id" = $1 LIMIT $2 [["id", 69], ["LIMIT", 1]]
22:32:33 web.1 | ↳ app/controllers/transactions_controller.rb:19:in `show'
22:32:33 web.1 | Rendering layout layouts/application.html.erb
22:32:33 web.1 | Rendering transactions/show.html.erb within layouts/application
22:32:33 web.1 | Rendered transactions/_transaction.html.erb (Duration: 0.4ms | Allocations: 143)
22:32:33 web.1 | Rendered shared/_destroy_modal.html.erb (Duration: 0.4ms | Allocations: 126)
22:32:33 web.1 | Rendered shared/_actions.html.erb (Duration: 0.7ms | Allocations: 243)
22:32:33 web.1 | Rendered transactions/show.html.erb within layouts/application (Duration: 1.6ms | Allocations: 580)
22:32:33 web.1 | Rendered shared/navbar/_resources_dropdown.html.erb (Duration: 0.1ms | Allocations: 66)
22:32:33 web.1 | Rendered shared/navbar/_statistics_dropdown.html.erb (Duration: 0.1ms | Allocations: 48)
22:32:33 web.1 | Rendered shared/navbar/_admin_dropdown.html.erb (Duration: 0.2ms | Allocations: 113)
22:32:33 web.1 | Rendered shared/navbar/_navbar.html.erb (Duration: 0.8ms | Allocations: 557)
22:32:33 web.1 | Rendered shared/_flash_messages.html.erb (Duration: 0.0ms | Allocations: 19)
22:32:33 web.1 | Rendered layout layouts/application.html.erb (Duration: 2.9ms | Allocations: 1529)
22:32:33 web.1 | Completed 200 OK in 17ms (Views: 3.3ms | ActiveRecord: 1.9ms | Allocations: 4808)
If I am correct, it should make a single HTML
request and I noticed that the first request has rendered a layout from here:
Rendered layout /usr/share/rvm/gems/ruby-3.2.2/gems/turbo-rails-1.5.0/app/views/layouts/turbo_rails/frame.html.erb (Duration: 3.0ms | Allocations: 679)
while the second request has been rendered from here:
Rendered layout layouts/application.html.erb (Duration: 2.9ms | Allocations: 1529)
This content is rendered from a partial _transactions.html.erb
to all.turbo_stream.erb
page while the show.html.erb
file also renders it making a single HTML
request w/o turbo stream.
So my question is, is it normal for the links in the turbo streams to make 2 requests to render a page? Has anyone experienced this issue?
FYI
- This bug isn't specific to an environment as I have also seen this in my production logs.
- This bug is also not specific to the
turbo-rails
version as it had the same bug in the previous version1.3.2
.
Current Specs
- ruby
3.2.2
- rails
7.1.2
- turbo-rails
1.5.0
I am not much experienced in the area of hotwire
or turbo
so I am not sure what to try and not. So if anyone has experience in this area, I would love your 2 cents on this! :)
Thanks!
If you look in your js console in your browser, you will most likely see something like "frame missing in response, doing full page load".
The links automatically target the "closest" turbo frame. Then Turbo expects a corresponding Turbo-Frame tag in the response, which is not there. In consequence, Turbo reloads the site with the entire layout (as in a Turbo-Drive request - what you originally intended).
To solve this, add
data-turbo-frame="_top"
to your links.See also: https://turbo.hotwired.dev/handbook/frames#targeting-navigation-into-or-out-of-a-frame