我正在尝试返回父记录列表以及每个父母最近的子记录。
在我的控制器中我有:
def index
projects = current_user.projects.includes(:tasks)
render json: projects.as_json(
methods: [:most_recent_task],
), status: 200
end
方法most_recent_task
使用明确的here方法,并总结如下:
class Task < ApplicationRecord
class << self
def in_order
order(created_at: :asc)
end
def recent(n)
in_order.endmost(n)
end
def endmost(n)
all.only(:order).from(all.reverse_order.limit(n), table_name)
end
end
end
和
class Project < ApplicationRecord
has_many :tasks
def most_recent_task
tasks.recent(1)[0]
end
end
这种方法返回正确的JSON响应,但我现在显然在每个请求上处理Task
的n + 1个查询。
我尝试使用:includes
和:limit
来链接范围,但似乎无法解决这个问题。也许使用JSON序列化器可以解决它?但我现在正试图避免这种额外的依赖。有什么建议吗?
答案 0 :(得分:1)
一种解决方案是定义具有关联范围的has_one:
has_one :most_recent_task, -> { order(created_at: :asc) }, class_name: "Task"
然后,您可以使用includes
急切加载数据:
>> Project.includes(:most_recent_task).all
Project Load (0.3ms) SELECT "projects".* FROM "projects" LIMIT $1 [["LIMIT", 11]]
Task Load (0.5ms) SELECT "tasks".* FROM "tasks" WHERE "tasks"."project_id" IN (1, 2) ORDER BY "tasks"."created_at" ASC
请注意,它正在查询每个项目的所有任务,而不仅仅是最近的任务。但是没有N + 1,Project#most_recent_task
很有表现力。