简体   繁体   中英

Sum by method in deep level associations

I've a model Task that has an has_many assocation with itself...it's a tree structure.

Now the problem is: I want do the sum of a 'field' (it's not a field in db, but the result is given by a method) of all his childrens recursively (I don't know how deep is the tree).

How can I do ?

I've this:

class Task < ActiveRecord::Base
  include PublicActivity::Common

  has_many :childrens, class_name: "Task", foreign_key: "parent_id"
  belongs_to :parent, class_name: "Task"

  def total_progress
    if self.childrens.present?
      (self.childrens.sum(:total_progress) / self.childrens.count)
    else
      self.progress / self.measure_target
    end
  end
end

Of course I know that I can't do self.childrens.sum, because sum is a done via SQL..but it's just for explain better what I want to do.

Thanks a lot for any advice.

You need to distinguish between children and descendants. Children are the direct children of the node, ie those that have "parent_id" set to the task's id.

You can get back the descendants with a method like this:

def descendants
  current_children = self.children
  all_children = []
  while current_children.size > 0
    all_children += current_children
    current_children = current_children.collect(&:children).flatten
  end
  all_children
end

and then get the total progress like so

def self_and_descendants
  [self] + self.descendants
end

def self_and_descendants_total_progress
  self.self_and_descendants.map(&:progress).sum
end  

EDIT - there are "smarter" tree structures which allow you to get all the descendant nodes in one hit. You might want to have a look at https://github.com/stefankroes/ancestry for example

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM