From e8a0768d97b63c81d6a313e3f6925843df17c692 Mon Sep 17 00:00:00 2001 From: cryptogopher Date: Fri, 25 Apr 2025 14:25:13 +0200 Subject: [PATCH] Update Quantity.depth using WITH + UPDATE ALL --- app/models/quantity.rb | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/app/models/quantity.rb b/app/models/quantity.rb index 4b82a89..992b168 100644 --- a/app/models/quantity.rb +++ b/app/models/quantity.rb @@ -19,7 +19,7 @@ class Quantity < ApplicationRecord validates :description, length: {maximum: type_for_attribute(:description).limit} # Update :depths of progenies after parent change - before_update if: :parent_changed? do + before_save if: :parent_changed? do self[:depth] = parent&.depth&.succ || 0 end @@ -27,32 +27,18 @@ class Quantity < ApplicationRecord quantities = Quantity.arel_table selected = Arel::Table.new('selected') - self.class.connection.update( - Arel::UpdateManager.new.table( - Arel::Nodes::JoinSource.new( - quantities, - [ - quantities.create_join( - # TODO: user .with(quanities: user.quantities) once the '?' problem is fixed - Quantity.with_recursive(selected: [ - quantities.project(quantities[:id], quantities[:depth]) - .where(quantities[:id].eq(id).and(quantities[:user_id].eq(user.id))), - quantities.project(quantities[:id], selected[:depth] + 1) - .join(selected).on(selected[:id].eq(quantities[:parent_id])) - ]).select(selected[Arel.star]).from(selected).arel.as('selected'), - quantities.create_on(quantities[:id].eq(selected[:id])) - ) - ] - ) - ).set(quantities[:depth] => selected[:depth]), - "#{self.class} Update All" - ) + Quantity.with_recursive(selected: [ + quantities.project(quantities[:id].as('quantity_id'), quantities[:depth]) + .where(quantities[:id].eq(id)), + quantities.project(quantities[:id], selected[:depth] + 1) + .join(selected).on(selected[:quantity_id].eq(quantities[:parent_id])) + ]).joins(:selected).update_all(depth: selected[:depth]) end # Update :pathnames of progenies after parent/name change PATHNAME_DELIMITER = ' → ' - before_update if: -> { parent_changed? || name_changed? } do + before_save if: -> { parent_changed? || name_changed? } do self[:pathname] = (parent ? parent.pathname + PATHNAME_DELIMITER : '') + self[:name] end