ruby-on-railsrubycallbackruby-on-rails-5.1nested-sets

after_save callback of act_as_nested_set model lead to SystemStackError


I am using Rails 5.1.6

I have a model called Taxon using acts_as_nested_set. I have 4 levels of Taxons, the last level sub_category has an attribute holding names of all parents, I want to update the sub_category attribute every time any of its parents name is changed, when using after_save callback it runs into SystemStackError as each after save callback is run for each child leading to infinite loop. Any idea how to overcome this issue?

class Taxon
  acts_as_nested_set dependent: :destroy

  def update_tree_name
  if shop_sub_category?
    update(display_tree_name: beautiful_name)
  else 
    related_sub_categories = tree_list.select{ |taxon| taxon.kind == "sub_category" }
    related_sub_categories.each do |t|
      t.update(display_tree_name: t.beautiful_name)
    end
  end
end


def beautiful_name
  "#{parent.parent.parent.name} -> #{parent.parent.name} -> #{parent.name}-> #{name}"
end

Solution

  • I have a solution that will work for you but I do not think it is an elegant one but here you go and then you can fine tune it:

    In your model:

    class Taxon < ActiveRecord::Base
      cattr_accessor :skip_callbacks
      after_save :update_tree_name, :unless => :skip_callbacks
    end
    
    def update_tree_name
      if shop_sub_category?
        update(display_tree_name: beautiful_name)
      else 
        related_sub_categories = tree_list.select{ |taxon| taxon.kind == "sub_category" }
        Taxon.skip_callbacks = true # disable the after_save callback so that you do not end up in infinite loop (stackoverflow)
        related_sub_categories.each do |t|
          t.update(display_tree_name: t.beautiful_name)
        end
        Taxon.skip_callbacks = false # enable callbacks again when you finish
      end
    end