I have 4 models
module Vehicle
has_many :routes
end
module Route
has_many :route_users
belongs_to :vehicle
end
module RouteUser
belongs_to :route
belongs_to :user
end
module User
belongs_to :route_user
end
My goal is to return the most recent driver (a user
) through the aggregate.rb
; to be specific, I need user id, first_name, last_name
.
attributes = {
id: vehicle.id,
... other attributes ...
}
attributes.merge!(
driver: {
id: vehicle.routes.last.route_users.last.user.id,
first_name: vehicle.routes.last.route_users.last.user.first_name,
last_name: vehicle.routes.last.route_users.last.user.last_name
}
) if vehicle.routes.present? && vehicle.routes.last.route_users.present?
As you can see, .merge!
loads a bunch of information and dramatically slows down the aggregate.rb
return. Is there any way to optimize this return to make it faster? Am I missing something?
CodePudding user response:
You can improve your User model to make the query easier.
class User < ApplicationRecord
has_many :route_users
has_many :routes, through: :route_users
has_many :vehicles, through: :routes
end
And when the query is big from one side, the best way is two invert the logic, and make a query from user, example:
First fetch last_user_drive, and after that, use his fields to merge into attributes
last_user_driver = User.joins(routes: :vehicle).where(vehicle: {id: vehicle.id}).order('routes.created_at').last
...
attributes.merge!(
driver: {
id: last_user_driver.id,
first_name: last_user_driver.first_name,
last_name: last_user_driver.last_name
}
) if last_user_driver.present?