forked from fixin.me/fixin.me
Turn #ancestors into #with_ancestors scope
This commit is contained in:
parent
27038a74d0
commit
2c0ae1530a
@ -93,28 +93,28 @@ class Quantity < ApplicationRecord
|
|||||||
user.quantities.progenies(self).to_a
|
user.quantities.progenies(self).to_a
|
||||||
end
|
end
|
||||||
|
|
||||||
# Return: ancestors of (possibly destroyed) self; include depths, also on
|
# Return: record `of` with its ancestors, sorted by `depth`
|
||||||
# self (unless destroyed)
|
scope :with_ancestors, ->(of) {
|
||||||
def ancestors
|
selected = Arel::Table.new('selected')
|
||||||
quantities = Quantity.arel_table
|
|
||||||
ancestors = Arel::Table.new('ancestors')
|
|
||||||
|
|
||||||
# Ancestors are listed bottom up, so it's impossible to know depth at the
|
model.with(selected: self).with_recursive(arel_table.name => [
|
||||||
# start. Start with depth = 0 and count downwards, then adjust by the
|
selected.project(selected[Arel.star], Arel::Nodes.build_quoted(0).as('depth'))
|
||||||
# amount needed to set biggest negative depth to 0.
|
.where(selected[:id].eq(of&.id)),
|
||||||
Quantity.with_recursive(ancestors: [
|
# Ancestors are listed bottom up, so it's impossible to know depth at the
|
||||||
user.quantities.select(quantities[Arel.star], Arel::Nodes.build_quoted(0).as('depth'))
|
# start. Start with depth = 0 and count downwards, then adjust by the
|
||||||
.where(id: parent_id),
|
# amount needed to set biggest negative depth to 0.
|
||||||
user.quantities.select(quantities[Arel.star], ancestors[:depth] - 1)
|
selected.project(selected[Arel.star], arel_table[:depth] - 1)
|
||||||
.joins(quantities.create_join(
|
.join(arel_table).on(selected[:id].eq(arel_table[:parent_id]))
|
||||||
ancestors, quantities.create_on(quantities[:id].eq(ancestors[:parent_id]))
|
]).select(
|
||||||
))
|
arel_table[Arel.star],
|
||||||
]).select(ancestors[Arel.star]).from(ancestors).to_a.then do |records|
|
(arel_table[:depth] + Arel::SelectManager.new.project(Arel.star.count).from(arel_table) - 1)
|
||||||
records.map(&:depth).min&.abs.then do |maxdepth|
|
.as('depth')
|
||||||
self.depth = maxdepth&.succ || 0 unless frozen?
|
).order(arel_table[:depth])
|
||||||
records.each { |r| r.depth += maxdepth }
|
}
|
||||||
end
|
|
||||||
end
|
# Return: ancestors of (possibly destroyed) self
|
||||||
|
def ancestors
|
||||||
|
user.quantities.with_ancestors(parent)
|
||||||
end
|
end
|
||||||
|
|
||||||
def ancestor_of?(descendant)
|
def ancestor_of?(descendant)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user