【问题标题】:Method to Pull All Child Objects is Updating Child Objects拉取所有子对象的方法是更新子对象
【发布时间】:2020-05-14 21:03:28
【问题描述】:

我有一个 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

每个项目都有_许多目标。

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

  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_include_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】:

    这是因为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
    

    最后会返回一个数组,这可能是也可能不是你要找的。​​p>

    另一种方法是获取所有 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)
    

    【讨论】:

    • @jfredson 很高兴听到
    猜你喜欢
    • 2019-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 2010-09-26
    • 2016-11-09
    相关资源
    最近更新 更多