提取所有子对象的方法正在更新子对象

问题描述 投票:0回答:1

我有一个Project模型,可以将自身作为定义为Project.projects的子项目。

class Project < ApplicationRecord
  belongs_to :parent_project, class_name: 'Project', optional: true
  has_many :projects, foreign_key: :parent_project_id, class_name: 'Project', dependent: :destroy
  has_many :goals
end

每个项目都有许多目标。

[我正在尝试在Project模型中编写一种方法,该方法将使我能够收集该项目的所有目标,以及所有子项目的子项目(递归)。

  def descendant_projects
    self.projects | self.projects.map(&:descendant_projects).flatten
  end

  def goals_including_descendants
    all_goals = self.goals
    descendant_projects.each do |project|
      all_goals.concat(project.goals)
    end
    all_goals
  end

[当我调用project.goals_includes_descendants时,将在数据库中更新子项目的project_id,以将其作为原始父项目的直接目标。此代码的哪一部分将导致Rails触发数据库更新?我可以在控制台中看到它:

  Goal Load (0.0ms)  SELECT "goals".* FROM "goals" WHERE "goals"."project_id" = $1  [["project_id", 49]]
   (0.0ms)  BEGIN
  SQL (0.2ms)  UPDATE "goals" SET "project_id" = $1, "updated_at" = $2 WHERE "goals"."id" = $3  [["project_id", 1], ["updated_at", "2020-05-14 20:47:47.761861"], ["id", 19]]

我完全为为什么发生这种情况而感到困惑。感谢您的见解。

ruby-on-rails activerecord rails-activerecord rails-models
1个回答
0
投票

因为concat将项目添加到self.goals AR Relation对象并立即更新,所以发生。

您可以通过将其转换为数组来解决此问题。

all_goals = self.goals.to_a

descendant_projects.each do |project|
  all_goals << project.goals.to_a
end

all_goals.flatten

将在最后返回一个数组,它可能不是您想要的。

另一种方法是获取所有ID。最后将返回一个Relation / Enumerable。

all_goals_ids = self.goals.ids

descendant_projects.each do |project|
  all_goals_ids << project.goals.ids
end

Goal.where(id: all_goals_ids)
© www.soinside.com 2019 - 2024. All rights reserved.