Rails action being called multiple times per request - ruby-on-rails

I have a controller action that's being called three times per browser request. Any ideas? config/routes.rb and application_controller.rb are totally straightforward.
Code below,
config/routes.rb
Rails.application.routes.draw do
root 'tiles#index'
+
controllers/tiles_controller.rb
class TilesController < ApplicationController
def index
puts "this line prints three times in the console per request"
end
+
tiles/index.html.erb
<% if notice %>
<p id="notice"><%= notice %></p>
<% end %>
<div id="tiles">
<%= render "tile", tile: { type: "sam", id: "0" } %>
<%= render "tile", tile: { type: "inputs", id: "1" } %>
<%= render collection: #tiles, partial: "tile" %>
<%= render "tile", tile: { type: "social", id: "1000" } %>
</div>
+
This is the console log:
log/development.log
Started GET "/" for 127.0.0.1 at 2017-08-31 16:56:28 -0400
Processing by TilesController#index as HTML
Started GET "/" for 127.0.0.1 at 2017-08-31 16:56:28 -0400
Processing by TilesController#index as HTML
[1m[36mProject Load (0.5ms)[0m [1m[34mSELECT "projects".* FROM "projects" ORDER BY "projects"."launch_date" ASC LIMIT $1[0m [["LIMIT", 10]]
[1m[36mProject Load (9.1ms)[0m [1m[34mSELECT "projects".* FROM "projects" ORDER BY "projects"."launch_date" ASC LIMIT $1[0m [["LIMIT", 10]]
Rendering tiles/index.html.erb within layouts/application
Rendered tiles/_tile_sam.html.erb (0.3ms)
Rendered tiles/_tile.html.erb (8.0ms)
Rendering tiles/index.html.erb within layouts/application
Rendered tiles/_tile_sam.html.erb (0.0ms)
Rendered tiles/_tile.html.erb (0.9ms)
Rendered tiles/_tile_instagram.html.erb (12.6ms)
...
Rendered tiles/_tile_twitter.html.erb (0.5ms)
Rendered collection of tiles/_tile.html.erb [48 times] (125.9ms)
Rendered tiles/_tile_project.html.erb (0.1ms)
Rendered tiles/_tile_social.html.erb (0.6ms)
Rendered tiles/_tile.html.erb (2.7ms)
Rendered tiles/index.html.erb within layouts/application (166.1ms)
Rendered tiles/_tile_twitter.html.erb (0.6ms)
...
Rendered collection of tiles/_tile.html.erb [48 times] (158.5ms)
Rendered tiles/_tile_social.html.erb (0.1ms)
Rendered tiles/_tile.html.erb (1.0ms)
Rendered tiles/index.html.erb within layouts/application (165.3ms)
Completed 200 OK in 1310ms (Views: 217.1ms | ActiveRecord: 9.1ms)
Completed 200 OK in 1325ms (Views: 204.5ms | ActiveRecord: 0.5ms)
Help!

WOW
Finally figured this one out by removing code related to this action/view line by line. Basically, I was generating a few img tags with empty src fields. Apparently this causes many modern browsers to load a website several times, possibly in an attempt to find missing images or assuming the root URL is the image itself?
Found the behavior cited here:
https://forums.asp.net/t/1804472.aspx?Bizzare+safari+thing+two+page+loads+for+each+page+
page loads twice in Google chrome

Related

Every time I add an image_tag to a page, the index is being rendered in the background (Rails 5)

I have a website with a large codebase.
I noticed that every page that is rendered and have a picture on it, after rendering the page, it makes another request to the index and loading everything in the background.
I have no idea why this happens.
Started GET "/ganenet/main" for ::1 at 2022-08-11 12:41:13 +0300
Processing by OwnersController#main as HTML
GanOwner Load (0.7ms) SELECT "gan_owners".* FROM "gan_owners" WHERE "gan_owners"."id" = $1 ORDER BY "gan_owners"."id" ASC LIMIT $2 [["id", 1], ["LIMIT", 1]]
Rendering owners/main.haml within layouts/application
Gan Load (0.4ms) SELECT "gans".* FROM "gans" WHERE "gans"."gan_owner_id" = $1 [["gan_owner_id", 1]]
Rendered owners/main.haml within layouts/application (6.4ms)
Rendered layouts/_google_tag_manager.haml (1.4ms)
Rendered layouts/_mixpanel.haml (2.2ms)
Rendered layouts/_hotjar.haml (1.9ms)
Rendered shared/_intercom.haml (2.5ms)
Rendered shared/_onesignal.html (0.3ms)
Rendered shared/_staging_env.haml (2.4ms)
Rendered shared/email_subscriptions/_consultant.html (0.4ms)
Rendered shared/modals/_consultant.haml (3.1ms)
Rendered shared/_modal.haml (8.5ms)
Rendered shared/_header.haml (18.4ms)
Rendered shared/owners/_navbar.haml (7.3ms)
Rendered shared/_gtm.haml (2.2ms)
Rendered shared/_modal.haml (11.5ms)
Rendered shared/_modal.haml (4.2ms)
Rendered shared/_modal.haml (57.8ms)
Rendered shared/modals/_ganenet_lekan.haml (83.3ms)
Rendered shared/_modal.haml (0.9ms)
Rendered shared/modals/_thankyou_contact_soon.haml (3.4ms)
Rendered shared/_modal.haml (0.5ms)
Rendered shared/modals/_thankyou_generic.haml (3.0ms)
Rendered shared/modals/_video_modal.haml (3.8ms)
Rendered shared/_footer.haml (3.0ms)
Rendered shared/_accessibility.html (0.2ms)
Completed 200 OK in 254ms (Views: 246.9ms | ActiveRecord: 1.1ms)
This is when the page I want is loaded, which is fine. But right after this, I get more requests which come out of nowhere.
Started GET "/dist/instantsearch.min.js.map" for ::1 at 2022-08-11 12:41:13 +0300
Started GET "/" for ::1 at 2022-08-11 12:41:13 +0300
Processing by HomeController#index as HTML
Started GET "/" for ::1 at 2022-08-11 12:41:13 +0300
Processing by HomeController#index as HTML
And it loads a bunch of stuff from the database which are related to the homepage (which is HomeController#index.
I noticed that the index loads only on pages that have at least one image on it.
I couldn't find any info on this issue so far.
Would be happy to hear from experienced folks with this issue.

File not received when sent with send_file in rails

I am sending file to client when they click on download in my application, however, the file don't get downloaded, by the client but the console indicates file been sent.
show.html.erb
<div class="col-10 music-detail">
<hr/>
<%= form_for :music, url: music_download_path do |f| %>
<%= f.hidden_field :music_id, value: #music.id %>
<%= f.submit :download, class:"download_btn "%>
<span class="sownload_count"><%= #music.download_count%></span>
<% end %>
</div>
MusicController.rb
def download
music_id = params[:music][:music_id]
music = Music.find(music_id)
if music.valid?
music_rel_path = music.music_path
music_file = gen_absolute_file_path music_rel_path
send_file(music_file)
download_count = music.download_count + 1
music.update(download_count: download_count)
redirect_to "/musics/#{music_id}"
end
end
rails server console output indicating file sent
Started POST "/music_download" for 127.0.0.1 at 2018-09-19 08:30:31 -0700
Processing by MusicsController#download as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"JmeNUnm7HgW8T55fALqQxN9a2v9MDKmJZCWsQ0MYfu3t1ETteowbAL UMB0bf9Tu0zxFFORNj2TmOgnWW8EARIQ==", "music"=>{"music_id"=>"2"}, "commit"=>"download"}
Music Load (0.0ms) SELECT "musics".* FROM "musics" WHERE "musics"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]]
Sent file C:/Users/USER/Desktop/projects/filmz_legendary/public/secure/musics/samuel_samuel-samuel/all_of_my_days.mp3 (48.5ms)
(0.0ms) begin transaction SQL (3.0ms) UPDATE "musics" SET "download_count" = ?, "updated_at" = ? WHERE "musics"."id" = ? [["download_count", 7], ["updated_at", "2018-09-19 15:30:32.789257"], ["id", 2]]
(202.7ms) commit transaction
Redirected to http://localhost:3000/musics/2
Completed 302 Found in 274ms (ActiveRecord: 205.7ms)
Started GET "/musics/2" for 127.0.0.1 at 2018-09-19 08:30:33 -0700
Processing by MusicsController#show as HTML
Parameters: {"id"=>"2"}
Music Load (0.0ms) SELECT "musics".* FROM "musics" WHERE "musics"."id" = ? LIMIT ? [["id", 2], ["LIMIT", 1]]
Rendering musics/show.html.erb within layouts/application
Rendered musics/show.html.erb within layouts/application (5.0ms)
Rendered layouts/_header.html.erb (1.0ms)
Rendered layouts/_footer.html.erb (1.0ms)
Completed 200 OK in 5278ms (Views: 5087.8ms | ActiveRecord: 0.0ms)
I am using :
ruby 2.3.3p222 (2016-11-21 revision 56859) [i386-mingw32]
ralis 5.1.6

Multiple Users views for signup in Ruby on Rails

I want to create two different signup pages. So from my home view I created these buttons:
<% if not logged_in? %>
<%= link_to "I'm a Hero", signup_path, class: "btn btn-lg btn-primary" %>
<%= link_to "I'm a villain", villain_path, class: "btn btn-lg btn-primary" %>
<% end %>
Now the route obviously looks like this for the "I'm a Hero" button:
get 'signup' => 'users#new'
I can render a nice signup form in views -> user -> new.html.erb. I was thinking that I can do the same for my "I'm a villain" button.
First I wanted to create a new file views -> user -> villain.html.erb. Then I wanted to create a route like this:
get 'villain' => 'users#villain'
If I now click on my "I'm a villain" button, basically nothing happens. And as for localhost:3000/villain, I get redirected to localhost:3000.
What did I miss?
This is the server log when clicking on "Im a villain"
Started GET "/villain" for 130.75.71.234 at 2017-03-11 14:07:00 +0000
Cannot render console from 130.75.71.234! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by UsersController#villain as HTML
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" IS NULL LIMIT 1
Redirected to https://ruby-project.c9users.io/
Completed 302 Found in 601ms (ActiveRecord: 1.5ms)
Started GET "/" for 130.75.71.234 at 2017-03-11 14:07:01 +0000
Cannot render console from 130.75.71.234! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by StaticPagesController#home as HTML
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" IS NULL LIMIT 1
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" IS NULL LIMIT 1
Rendered static_pages/home.html.erb within layouts/application (4.6ms)
Rendered layouts/_shim.html.erb (0.5ms)
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" IS NULL LIMIT 1
Rendered layouts/_header.html.erb (2.0ms)
Rendered layouts/_footer.html.erb (0.8ms)
Completed 200 OK in 386ms (Views: 381.7ms | ActiveRecord: 0.5ms)
You need to define the "villain" action in the controller. You probably have the "new" action already defined because you created it through the generator. That is probably why the "new" action does work and not the "villain" one.

Rails Controller Action being called twice

In my rails app, I have a link so that a user can download a GIF on the site:
<%= link_to "gif", :controller => "projects", :action => :export_gif, :id => #project.id %>
This is the corresponding controller action:
def export_gif
if #project.gif.blank?
#project.generate_gif #this creates #project.gif
end
gif_path = #project.gif.gif_file_url
gif_path.sub! 'https', 'http'
send_data open(gif_path).read, filename: "project_#{#project.id}.gif", type: "image/gif"
end
When the user clicks on the link, the export_gif action is being called twice. How do I ensure that it only gets called once?
Here's what the logs look like after I click the link:
Started GET "/projects/38/export_gif" for ::1 at 2015-06-16 17:08:55 -0400
Processing by ProjectsController#export_gif as HTML
Parameters: {"id"=>"38"}
Project Load (0.1ms) SELECT "projects".* FROM "projects" WHERE "projects"."id" = ? LIMIT 1 [["id", 38]]
Gif Load (0.1ms) SELECT "gifs".* FROM "gifs" WHERE "gifs"."project_id" = ? LIMIT 1 [["project_id", 38]]
Rendered text template (0.0ms)
Sent data project_38.gif (3.6ms)
Completed 200 OK in 207ms (Views: 3.4ms | ActiveRecord: 0.2ms)
Started GET "/projects/38/export_gif" for ::1 at 2015-06-16 17:08:55 -0400
Processing by ProjectsController#export_gif as HTML
Parameters: {"id"=>"38"}
Project Load (0.1ms) SELECT "projects".* FROM "projects" WHERE "projects"."id" = ? LIMIT 1 [["id", 38]]
Gif Load (0.1ms) SELECT "gifs".* FROM "gifs" WHERE "gifs"."project_id" = ? LIMIT 1 [["project_id", 38]]
Rendered text template (0.0ms)
Sent data project_38.gif (0.6ms)
Completed 200 OK in 196ms (Views: 0.5ms | ActiveRecord: 0.1ms)
For me it was because of <img src="#">. I had this in one of the files of layouts.
So I changed "#" with "http://example.com" and issue got resolved.
I got this solution from here(aNoble's answer):
Rails seems to be serving the page twice

How do I debug what takes a partial to render so long in rails?

Rendered cars/_handover_instruction_fields.html.slim (5.5ms)
Rendered cars/_handover_instruction_fields.html.slim (0.6ms)
Rendered cars/_handover_instruction_fields.html.slim (0.5ms)
Rendered cars/_handover_instruction_fields.html.slim (0.5ms)
Rendered cars/_handover_instruction_fields.html.slim (0.5ms)
Rendered cars/_handover_instruction_fields.html.slim (0.5ms)
Rendered cars/_edit_handover.html.slim (30.7ms)
Rendered cars/_edit_vrd.html.slim (5.2ms)
Rendered cars/_edit_features.html.slim (3.5ms)
Rendered cars/_edit_description.html.slim (5.2ms)
CarPhoto Load (0.5ms) SELECT "car_photos".* FROM "car_photos" WHERE "car_photos"."car_id" = $1 [["car_id", 19]]
Rendered cars/_photo_fields.html.slim (217.0ms)
Rendered cars/_photo_fields.html.slim (1.5ms)
Rendered cars/_photo_fields.html.slim (1.1ms)
Rendered cars/_photo_fields.html.slim (1.1ms)
Rendered cars/_photo_fields.html.slim (1.1ms)
Rendered cars/_photo_fields.html.slim (1.0ms)
Rendered cars/_photo_fields.html.slim (1.1ms)
Rendered cars/_photo_fields.html.slim (1.0ms)
Rendered cars/_edit_photos.html.slim (254.6ms)
Rendered cars/_edit_js.html.erb (0.5ms)
Rendered cars/edit.html.slim within layouts/application (356.7ms)
Rendered shared/_flash.html.slim (5.5ms)
Rendered shared/_slideout_nav.html.slim (16.9ms)
Rendered svgs/_carshare_typeface_blue_small.html (0.8ms)
Rendered shared/_header_nav.html.slim (20.1ms)
Above is an excerpt of the Rails.logger when I render one of the pages in my webapp. I realised some of the partial takes suspciously long to render.
For example
Rendered cars/_photo_fields.html.slim (217.0ms)
Rendered cars/_photo_fields.html.slim (1.5ms)
I want to find out what makes the rendering so long and how i can improve it.
<% benchmark("Showing projects partial") do %>
<%= render #projects %>
<% end %>
looks interesting.
A tip in general, if you have many #items don't call render each time. This saves you time.
#items.each do |item|
render 'one_item', :item => item
end
Instead render one time with a collection for example.
Check your logs and it will show you the database queries being generated. This is usually the first place to look and it will highlight where you can make performance improvements by optimising your queries. The obvious one is to check if you can benefit from N + 1 queries using includes.
There are other steps you can take as well, such as adding indices, using pluck if you only need to get individual attributes, using LIMIT and avoid sorting.

Resources