Active Model Serializer - Increasing Render Performance - ruby-on-rails

I'm running into a particular situation where the rendered json generated by ActiveModel::Serializer is extraordinary slow (around 6-8 seconds). How can I improve the speed of this rendering? Here's the code.
Models:
class Comment < ActiveRecord::Base
has_many :children_comments,
class_name: 'Comment',
foreign_key: 'parent_comment_id'
belongs_to :user
belongs_to :parent_comment,
class_name: 'Comment',
foreign_key: 'parent_comment_id'
end
Serializers:
class CommentSerializer < ActiveModel::Serializer
include ActionView::Helpers::DateHelper
attributes :id, :message, :created_at_in_words,
:created_at, :parent_comment_id
belongs_to :user
has_many :children_comments
def created_at_in_words
time_ago_in_words(object.created_at) + ' ago'
end
def children_comments
object.children_comments.map do |comment|
CommentSerializer.new(comment).as_json
end
end
end
class UserSerializer < ActiveModel::Serializer
attributes :id, :name, :avatar_url
def avatar_url
object.avatar.url
end
end
In my controller I have
parent_comments = Comment.where(parent_comment_id: nil)
render status: :ok,
json: parent_comments,
each_serializer: CommentSerializer,
key_transform: :camel_lower
Here is my partial log output when I make the call to the server. As you ca see Active Model Serializer is taking around 20ms to make each query call.
Started GET "/comments?lesson_id=420" for ::1 at 2016-09-01 11:09:14 -0400
Processing by Api::CommentsController#index as HTML
Parameters: {"lesson_id"=>"420"}
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT 1 [["id", 102]]
Lesson Load (0.5ms) SELECT "lessons".* FROM "lessons" WHERE "lessons"."id" = $1 ORDER BY position ASC LIMIT 1 [["id", 420]]
Comment Load (53.0ms) SELECT "comments".* FROM "comments" WHERE "comments"."commentable_id" = $1 AND "comments"."commentable_type" = $2 AND "comments"."parent_comment_id" IS NULL [["commentable_id", 420], ["commentable_type", "Lesson"]]
[active_model_serializers] User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (24.6ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41401]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (20.3ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41402]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (22.7ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41403]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (21.6ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41404]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.4ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41405]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (20.5ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41406]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (20.4ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41407]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (20.3ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41408]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.6ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41409]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.7ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41410]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.2ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41411]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.4ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41412]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.8ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41413]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (23.5ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41414]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.1ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41415]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.4ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41416]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (23.7ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41417]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.5ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41418]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.6ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41419]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.7ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41420]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.4ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41421]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.9ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41422]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.6ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41423]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (20.1ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41424]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.8ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41425]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.7ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41426]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.2ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41427]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.6ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41428]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.6ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41429]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.6ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41430]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.9ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41431]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.1ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41432]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.3ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41433]]
[active_model_serializers] CACHE (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (21.1ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41434]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.8ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41435]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (21.5ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41436]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.4ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41437]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.8ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41438]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (22.9ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41439]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.7ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41440]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.4ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41441]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.9ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41442]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.8ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41443]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.7ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41444]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.2ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41445]]
[active_model_serializers] CACHE (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.7ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41446]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.5ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41447]]
[active_model_serializers] CACHE (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.5ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41448]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.1ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41449]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.0ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41450]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.2ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41451]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.3ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41452]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.2ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41453]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.0ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41454]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (22.1ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41455]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (22.1ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41456]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.7ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41457]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.1ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41458]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.2ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41459]]
[active_model_serializers] CACHE (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.5ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41460]]
[active_model_serializers] CACHE (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (20.1ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41461]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.1ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41462]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.6ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41463]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.1ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41464]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (20.3ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41465]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.6ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41466]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.8ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41467]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.5ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41468]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.3ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41469]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.7ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41470]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.0ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41471]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (20.4ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41472]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.4ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41473]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.0ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41474]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.3ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41475]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.6ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41476]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (19.1ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41477]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.1ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41478]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.8ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41479]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (20.4ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41480]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.2ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41534]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.3ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41535]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.6ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41536]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.8ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41537]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (18.3ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 41538]]
[active_model_serializers] Rendered ActiveModel::Serializer::CollectionSerializer with ActiveModelSerializers::Adapter::Json (3895.33ms)
Completed 200 OK in 4007ms (Views: 1222.1ms | ActiveRecord: 2743.8ms)
With Michal's answer, here is a small sample from the log.
Started GET "/comments?lesson_id=370" for ::1 at 2016-09-02 17:13:06 -0400
Processing by Api::CommentsController#index as HTML
Parameters: {"lesson_id"=>"370"}
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT 1 [["id", 102]]
Lesson Load (0.4ms) SELECT "lessons".* FROM "lessons" WHERE "lessons"."id" = $1 ORDER BY position ASC LIMIT 1 [["id", 370]]
Comment Load (23.0ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" IS NULL AND "comments"."commentable_type" = 'Lesson' AND "comments"."commentable_id" = 370
User Load (0.9ms) SELECT "users".* FROM "users" WHERE "users"."id" IN (102)
Comment Load (25.7ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" IN (38641, 38687, 38733)
CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" IN (102)
[active_model_serializers] Comment Load (20.3ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 38642]]
[active_model_serializers] User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (20.7ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 38643]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
[active_model_serializers] Comment Load (30.1ms) SELECT "comments".* FROM "comments" WHERE "comments"."parent_comment_id" = $1 [["parent_comment_id", 38644]]
[active_model_serializers] CACHE (0.0ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 102]]
My theory is this. I'm convinced the children_comments serialization is causing the majority of the performance problems. Because I have to call children_comments for every comment, this results in a cascading effect. I wonder if I can rewrite the code in a way to improve performance.

You're running into a n+1 queries type problem. Unfortunately includes isn't really helping you here because it only helps you with one level of the association - it avoids separate fetches of the children of the top level comment, but not grand children or great grandchildren.
You could probably optimise the user lookup by maintaining your own cache of user id to user objects (the rails cache caches the raw data but will be reinstantiating the objects over and over again), but to make this substantially faster you need to change how you load the comments.
If you are using a database that supports it (such as postgresql), then recursive queries ar an option (see https://hashrocket.com/blog/posts/recursive-sql-in-activerecord for a worked example). I don't know this scales as the tree gets deeper and deeper.
If recursive queries aren't an option, then there are a few approaches that involve changing what you store.
One is the materialised path patten. For example say that the root comment has id 1, a child has id 101 and one of its children has id 426. That last comment's path is 1/101/426. All of its siblings have paths starting with 1/101/. This means you can use like queries (with wildcards at the end) to find subtrees quickly. The ancestry gem implements this. If comments get moved then you need to rewrite the paths of all the comments children (and grand children etc.), but that may not be relevant to your use case. Very deep trees are problematic I think.
Another is the nested set pattern. The core idea is that the parent node stores the minimum and maximum id of all of its children and their children's children etc. This allows retrieving of all these children in one go. The flip side is that inserts and updates require rewriting a lot of this data (more so than with materialised path). There have been various gems that implement this over the years (a current one seems to be awesome_nested_set).
Also worth checking that you have got the right indexes to support your queries - unless there are really quite a lot of comments with a given parent, 20-30ms seems quite a long time for one query.

Change your ActiveRecord query to this
parent_comments = Comment.where(parent_comment_id: nil).includes(:user, children_comments: :user)
It will get rid of N + 1 queries.

Related

Rails 6.1 eager load ActiveStorage::VariantRecord

I have been eager loading ActiveStorage attachments as follows:
Journey.includes(created_by_user: [profile_picture_attachment: :blob])
We have been using variants and every since we upgraded to Rails 6.1 and enabled tracking Active Storage variants in database, we notice n+1 queries in the logs because of a loop as follows:
Journey.includes(created_by_user: [profile_picture_attachment: :blob]).each do |j|
j.created_by_user.profile_picture.variant(resize_to_fill: [32, 32]).processed
end
Journey Load (0.8ms) SELECT "journeys".* FROM "journeys"
User Load (0.7ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 [["id", 607]]
ActiveStorage::Attachment Load (0.6ms) SELECT "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_type" = $1 AND "active_storage_attachments"."name" = $2 AND "active_storage_attachments"."record_id" = $3 [["record_type", "User"], ["name", "profile_picture"], ["record_id", 607]]
ActiveStorage::Blob Load (0.6ms) SELECT "active_storage_blobs".* FROM "active_storage_blobs" WHERE "active_storage_blobs"."id" = $1 [["id", 144]]
ActiveStorage::VariantRecord Load (0.5ms) SELECT "active_storage_variant_records".* FROM "active_storage_variant_records" WHERE "active_storage_variant_records"."blob_id" = $1 AND "active_storage_variant_records"."variation_digest" = $2 LIMIT $3 [["blob_id", 144], ["variation_digest", "k9S9jJS87DbFgXD1sW9j5XkOr1c="], ["LIMIT", 1]]
ActiveStorage::VariantRecord Load (0.5ms) SELECT "active_storage_variant_records".* FROM "active_storage_variant_records" WHERE "active_storage_variant_records"."blob_id" = $1 AND "active_storage_variant_records"."variation_digest" = $2 LIMIT $3 [["blob_id", 144], ["variation_digest", "k9S9jJS87DbFgXD1sW9j5XkOr1c="], ["LIMIT", 1]]
ActiveStorage::VariantRecord Load (0.5ms) SELECT "active_storage_variant_records".* FROM "active_storage_variant_records" WHERE "active_storage_variant_records"."blob_id" = $1 AND "active_storage_variant_records"."variation_digest" = $2 LIMIT $3 [["blob_id", 144], ["variation_digest", "k9S9jJS87DbFgXD1sW9j5XkOr1c="], ["LIMIT", 1]]
ActiveStorage::VariantRecord Load (0.5ms) SELECT "active_storage_variant_records".* FROM "active_storage_variant_records" WHERE "active_storage_variant_records"."blob_id" = $1 AND "active_storage_variant_records"."variation_digest" = $2 LIMIT $3 [["blob_id", 144], ["variation_digest", "k9S9jJS87DbFgXD1sW9j5XkOr1c="], ["LIMIT", 1]]
ActiveStorage::VariantRecord Load (0.5ms) SELECT "active_storage_variant_records".* FROM "active_storage_variant_records" WHERE "active_storage_variant_records"."blob_id" = $1 AND "active_storage_variant_records"."variation_digest" = $2 LIMIT $3 [["blob_id", 144], ["variation_digest", "k9S9jJS87DbFgXD1sW9j5XkOr1c="], ["LIMIT", 1]]
I tried to eager load with the following but it doesn't seem to work:
Journey.includes(created_by_user: [profile_picture_attachment: { blob: :variant_records }])
Has anyone tried eager loading the tracked variant records to share your ideas?
Turns out there is a pull request addressing exactly this. For anyone looking for a solution, please follow the merge request.
https://github.com/rails/rails/pull/37901
It eventually winds its way to a secondary PR, which allows eager loading the stored variants. It's now merged into future versions of Rails, here was the code they used to eager load variants:
https://github.com/rails/rails/pull/40842/files

Stop rails loading associated models when checkin if record is valid

I have an object called message which belongs to carrier, company, country
I allowing for a bulk insert of users via a CSV - what i want to do before is make sure every row is valid before i import it (so that i can inform the user prior to the beginning the import)
So i have created a method that loops through all new data and does Message.new(PARAMS_IN_HERE) and then call .valid? on it, which is fine and achieves the desired results.
However, when i look in the logs i see loads of queries like this
Country Load (0.2ms) SELECT "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Carrier Load (0.2ms) SELECT "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Company Load (0.2ms) SELECT "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Country Load (0.2ms) SELECT "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Carrier Load (0.2ms) SELECT "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Company Load (0.2ms) SELECT "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Country Load (0.2ms) SELECT "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Carrier Load (0.2ms) SELECT "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Company Load (0.2ms) SELECT "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Country Load (0.2ms) SELECT "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Carrier Load (0.2ms) SELECT "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Company Load (0.2ms) SELECT "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Country Load (0.2ms) SELECT "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Carrier Load (0.2ms) SELECT "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Company Load (0.2ms) SELECT "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Country Load (0.2ms) SELECT "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Carrier Load (0.2ms) SELECT "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Company Load (0.2ms) SELECT "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Country Load (0.2ms) SELECT "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Carrier Load (0.2ms) SELECT "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Company Load (0.2ms) SELECT "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Country Load (0.2ms) SELECT "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Carrier Load (0.2ms) SELECT "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Company Load (0.2ms) SELECT "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Country Load (0.2ms) SELECT "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Carrier Load (0.2ms) SELECT "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Company Load (0.2ms) SELECT "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Country Load (0.2ms) SELECT "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Carrier Load (0.2ms) SELECT "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Company Load (0.2ms) SELECT "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Country Load (0.2ms) SELECT "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Carrier Load (0.2ms) SELECT "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Company Load (0.2ms) SELECT "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Country Load (0.3ms) SELECT "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Carrier Load (0.2ms) SELECT "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Company Load (0.2ms) SELECT "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Country Load (0.2ms) SELECT "countries".* FROM "countries" WHERE "countries"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Carrier Load (0.2ms) SELECT "carriers".* FROM "carriers" WHERE "carriers"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Which is obviously quite wasteful as one its doing the same query multiple times. Is there a way to make rails cache the value/preload when it needs to look for/ or just stop it happening?
This is what my message class look like
class Message < ApplicationRecord
belongs_to :company
belongs_to :carrier
belongs_to :country
before_validation :set_default_details, on: :create
private
def set_default_details
if self.user.present?
self.carrier_id = self.user.company.tariff.carrier_id
self.country_id = self.user.country_id
self.company_id = self.user.company_id
end
end
end
Your validation references self.user but that's not defined in the model snippet you posted.
If your validations refer to to association objects, like self.company, give those objects to the constructor: Message.new(company: company) rather than Message.new(company_id: company.id). If necessary look up all dependent objects ahead of time - this can be done with a single query - and store id -> object mapping in a Hash.
Similarly you can have validations reference fields like company_id but it's probably better to use association objects everywhere.

Double everything in my db logs Rails

I have double everything in my logs. Not sure how to get rid of it. Any suggestions?
Bid Load (0.2ms) SELECT "bids".* FROM "bids" WHERE "bids"."order_id" = $1 [["order_id", 7]]
Bid Load (0.2ms) SELECT "bids".* FROM "bids" WHERE "bids"."order_id" = $1 [["order_id", 7]]
Size Load (0.2ms) SELECT "sizes".* FROM "sizes" WHERE "sizes"."order_id" = $1 LIMIT 1 [["order_id", 7]]
Size Load (0.2ms) SELECT "sizes".* FROM "sizes" WHERE "sizes"."order_id" = $1 LIMIT 1 [["order_id", 7]]
Bid Load (0.2ms) SELECT "bids".* FROM "bids" WHERE "bids"."order_id" = $1 [["order_id", 8]]
Bid Load (0.2ms) SELECT "bids".* FROM "bids" WHERE "bids"."order_id" = $1 [["order_id", 8]]
Size Load (0.3ms) SELECT "sizes".* FROM "sizes" WHERE "sizes"."order_id" = $1 LIMIT 1 [["order_id", 8]]
Size Load (0.3ms) SELECT "sizes".* FROM "sizes" WHERE "sizes"."order_id" = $1 LIMIT 1 [["order_id", 8]]
Bid Load (0.2ms) SELECT "bids".* FROM "bids" WHERE "bids"."order_id" = $1 [["order_id", 9]]
Bid Load (0.2ms) SELECT "bids".* FROM "bids" WHERE "bids"."order_id" = $1 [["order_id", 9]]
Size Load (0.2ms) SELECT "sizes".* FROM "sizes" WHERE "sizes"."order_id" = $1 LIMIT 1 [["order_id", 9]]
Size Load (0.2ms) SELECT "sizes".* FROM "sizes" WHERE "sizes"."order_id" = $1 LIMIT 1 [["order_id", 9]]
Bid Load (0.2ms) SELECT "bids".* FROM "bids" WHERE "bids"."order_id" = $1 [["order_id", 10]]
Bid Load (0.2ms) SELECT "bids".* FROM "bids" WHERE "bids"."order_id" = $1 [["order_id", 10]]
CACHE (0.0ms) SELECT "printers".* FROM "printers" WHERE "printers"."id" = $1 LIMIT 1 [["id", 1]]
CACHE (0.0ms) SELECT "printers".* FROM "printers" WHERE "printers"."id" = $1 LIMIT 1 [["id", 1]]
Size Load (0.2ms) SELECT "sizes".* FROM "sizes" WHERE "sizes"."order_id" = $1 LIMIT 1 [["order_id", 10]]
Size Load (0.2ms) SELECT "sizes".* FROM "sizes" WHERE "sizes"."order_id" = $1 LIMIT 1 [["order_id", 10]]
Rails Version Rails 4.2.5
Ruby Version 2.3.0
you can add the following to application.rb
if Rails.env.development?
# Don't log to STDOUT, by default rails s will handle it
config.logger = Logger.new('/dev/null')
else
# Don't log to file, sending everything to unicorn file.
config.logger = Logger.new(STDOUT)
end
Basically rails server and rails logger both send their messages to stdout which results in duplication in the logs.

Rails 4 ActiveRecord multiple queries

I use rails 4.2.5.
I have some sort of N+1 problem in this code
seats=SeatItem.where(:b => hall.id).all
seats.each do |seat|
arr << Ticket.new(:a => seat.id)
end
Ticket.import arr
Problem of this code is that i have this in log
MIT 1 [["id", 13]]
CACHE (0.0ms) SELECT "seat_item_types".* FROM "seat_item_types" WHERE "seat_item_types"."id" = $1 LIMIT 1 [["id", 13]]
CACHE (0.0ms) SELECT "seat_item_types".* FROM "seat_item_types" WHERE "seat_item_types"."id" = $1 LIMIT 1 [["id", 13]]
CACHE (0.0ms) SELECT "seat_item_types".* FROM "seat_item_types" WHERE "seat_item_types"."id" = $1 LIMIT 1 [["id", 13]]
CACHE (0.0ms) SELECT "seat_item_types".* FROM "seat_item_types" WHERE "seat_item_types"."id" = $1 LIMIT 1 [["id", 13]]
CACHE (0.0ms) SELECT "seat_item_types".* FROM "seat_item_types" WHERE "seat_item_types"."id" = $1 LIMIT 1 [["id", 13]]
CACHE (0.0ms) SELECT "seat_item_types".* FROM "seat_item_types" WHERE "seat_item_types"."id" = $1 LIMIT 1 [["id", 13]]
CACHE (0.0ms) SELECT "seat_item_types".* FROM "seat_item_types" WHERE "seat_item_types"."id" = $1 LIMIT 1 [["id", 13]]
CACHE (0.0ms) SELECT "seat_item_types".* FROM "seat_item_types" WHERE "seat_item_types"."id" = $1 LIMIT 1 [["id", 13]]
CACHE (0.0ms) SELECT "seat_item_types".* FROM "seat_item_types" WHERE "seat_item_types"."id" = $1 LIMIT 1 [["id", 13]]
CACHE (0.0ms) SELECT "seat_item_types".* FROM "seat_item_types" WHERE "seat_item_types"."id" = $1 LIMIT 1 [["id", 13]]
CACHE (0.0ms) SELECT "seat_item_types".* FROM "seat_item_types" WHERE "seat_item_types"."id" = $1 LIMIT 1 [["id", 13]]
CACHE (0.0ms) SELECT "seat_item_types".* FROM "seat_item_types" WHERE "seat_item_types"."id" = $1 LIMIT 1 [["id", 13]]
CACHE (0.0ms) SELECT "seat_item_types".* FROM "seat_item_types" WHERE
Why :all method does not load all in memory and how fix it?
Thank you for your input!
I don't think :all is the problem. Notice that the repeated SQL query is identical and that it's fetching rows from seat_item_types not seat_items. My guess is that you have a before/after hook or some other code that is being triggered by Ticket.new or Ticket.import that is accessing seat_item_type.
You should use eager_load for solve N + 1 query problem
use includes method like this
clients = Client.includes(:address).limit(10)
clients.each do |client|
puts client.address.postcode
end
http://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations
But first of all, I think you define associations on SeatItem and Ticket
http://guides.rubyonrails.org/association_basics.html

Rails validation for presence is incorrently throwing error

I'm using Ruby on Rails 4.x and I have a presence validator for the due date of an "rfq". But this validator always throws the error even if the due date is set!
Here is the validation in question (rfq.rb):
validates :due, presence:{ message:" date must be set"}
I think it has something to do with this line in my controller for the same model:
if #rfq.due.present?
#rfq.due = Date.strptime(rfq_params[:due].to_str,"%m-%d-%Y")
#rfq.due = #rfq.due.change(hour: 15)
end
any help is appreciated.
EDIT: added trace (I hope, still new to this)
Started POST "/rfqs" for 192.168.1.29 at 2015-08-17 15:45:39 -0500
Cannot render console from 192.168.1.29! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255
Processing by RfqsController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"BfYwpLx5jos+lZCAnefuwgIK1UCW5Lh1xo6V72v9Hlw8JPl8igQrD8Tiuhfo0vvCYIyBdMV/PDEQqImTrvhQDg==", "rfq"=>{"customer_name"=>"Matha Laswell", "customer_id"=>"8", "priority"=>"LOW", "vendor_id"=>"1", "placeholder"=>"1", "due"=>"08-18-2015", "mandatory_due_date"=>"0", "is_budgetary"=>"0", "ship_date"=>"standard", "end_user_list"=>"", "application_list"=>"", "notes"=>""}, "weeks"=>"1", "commit"=>"Create Rfq"}
[1m[36mUser Load (0.5ms)[0m [1mSELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1[0m [["id", 4]]
Unpermitted parameter: priority
[1m[35mCustomer Load (0.1ms)[0m SELECT "customers".* FROM "customers" WHERE "customers"."id" = ? LIMIT 1 [["id", 8]]
[1m[36m (0.2ms)[0m [1mbegin transaction[0m
[1m[35m (0.1ms)[0m rollback transaction
[1m[36mVendor Load (0.2ms)[0m [1mSELECT "vendors".* FROM "vendors"[0m
Rendered rfqs/_rfq_attachment_fields.html.slim (0.9ms)
Rendered rfqs/_quote_fields.html.slim (0.7ms)
[1m[35mVendor Load (0.1ms)[0m SELECT "vendors".* FROM "vendors" WHERE "vendors"."id" = ? LIMIT 1 [["id", 1]]
[1m[36mFormAttribute Load (0.1ms)[0m [1mSELECT "form_attributes".* FROM "form_attributes" WHERE "form_attributes"."vendor_id" = ? AND (attribute = 'productline')[0m [["vendor_id", 1]]
[1m[35mCACHE (0.0ms)[0m SELECT "vendors".* FROM "vendors" WHERE "vendors"."id" = ? LIMIT 1 [["id", 1]]
[1m[36mFormAttribute Load (0.1ms)[0m [1mSELECT "form_attributes".* FROM "form_attributes" WHERE "form_attributes"."vendor_id" = ? AND (attribute = 'discwedge')[0m [["vendor_id", 1]]
[1m[35mCACHE (0.0ms)[0m SELECT "vendors".* FROM "vendors" WHERE "vendors"."id" = ? LIMIT 1 [["id", 1]]
[1m[36mFormAttribute Load (0.1ms)[0m [1mSELECT "form_attributes".* FROM "form_attributes" WHERE "form_attributes"."vendor_id" = ? AND (attribute = 'valvetype')[0m [["vendor_id", 1]]
[1m[35mCACHE (0.0ms)[0m SELECT "vendors".* FROM "vendors" WHERE "vendors"."id" = ? LIMIT 1 [["id", 1]]
[1m[36mFormAttribute Load (0.1ms)[0m [1mSELECT "form_attributes".* FROM "form_attributes" WHERE "form_attributes"."vendor_id" = ? AND (attribute = 'valveends')[0m [["vendor_id", 1]]
[1m[35mCACHE (0.0ms)[0m SELECT "vendors".* FROM "vendors" WHERE "vendors"."id" = ? LIMIT 1 [["id", 1]]
[1m[36mFormAttribute Load (0.1ms)[0m [1mSELECT "form_attributes".* FROM "form_attributes" WHERE "form_attributes"."vendor_id" = ? AND (attribute = 'valvematerial')[0m [["vendor_id", 1]]
[1m[35mCACHE (0.0ms)[0m SELECT "vendors".* FROM "vendors" WHERE "vendors"."id" = ? LIMIT 1 [["id", 1]]
[1m[36mFormAttribute Load (0.1ms)[0m [1mSELECT "form_attributes".* FROM "form_attributes" WHERE "form_attributes"."vendor_id" = ? AND (attribute = 'valveconfig')[0m [["vendor_id", 1]]
[1m[35mCACHE (0.0ms)[0m SELECT "vendors".* FROM "vendors" WHERE "vendors"."id" = ? LIMIT 1 [["id", 1]]
[1m[36mFormAttribute Load (0.1ms)[0m [1mSELECT "form_attributes".* FROM "form_attributes" WHERE "form_attributes"."vendor_id" = ? AND (attribute = 'class')[0m [["vendor_id", 1]]
[1m[35mCACHE (0.0ms)[0m SELECT "vendors".* FROM "vendors" WHERE "vendors"."id" = ? LIMIT 1 [["id", 1]]
[1m[36mFormAttribute Load (0.1ms)[0m [1mSELECT "form_attributes".* FROM "form_attributes" WHERE "form_attributes"."vendor_id" = ? AND (attribute = 'operator')[0m [["vendor_id", 1]]
Rendered rfqs/_line_item_fields.html.slim (4.6ms)
Rendered rfqs/_valve_fields_xanik.html.slim (19.3ms)
Rendered rfqs/_form.html.slim (49.7ms)
Rendered rfqs/new.html.slim within layouts/application (50.9ms)
Completed 200 OK in 1519ms (Views: 1496.4ms | ActiveRecord: 2.1ms)
EDIT: accidentally fixed it
So I changed
#rfq = Rfq.new(rfq_params)
#rfq.owner = current_user.first_name.titleize
if #rfq.due.present?
#rfq.due = Date.strptime(rfq_params[:due].to_str,"%m-%d-%Y")
#rfq.due = #rfq.due.change(hour: 15)
end
to
#rfq = Rfq.new(rfq_params)
#rfq.owner = current_user.first_name.titleize
if rfq_params[:due].present?
#rfq.due = Date.strptime(rfq_params[:due].to_str,"%m-%d-%Y")
#rfq.due = #rfq.due.change(hour: 15)
end
and now it works but I don't really understand why...
Sorry if this is obvious, I'm just new to Rails

Resources