Слишком глубокий уровень стека при вызове remove_from_list из гема act_as_list

Я запускаю тест, который не давал сбоев до обновления до rails 5.0, но теперь я получаю слишком глубокий уровень стека, тест выглядит следующим образом:

describe "item hierarchy" do
    before(:each) do
      @template = FactoryGirl.create(:item_template)
      @root_item_a = FactoryGirl.create(:item, :parent => @template)
      @root_item_b = FactoryGirl.create(:item, :parent => @template)
    end
    it "allows a root item without children to be moved under another item" do
      @root_item_a.parent_item = @root_item_b
      expect(@root_item_a).to be_valid
      expect(@root_item_a.save).to be_truthy

      @root_item_a.reload
      expect(@root_item_a.parent_item).to eql @root_item_b
    end

Контроллер имеет следующий соответствующий код:

belongs_to :parent_item, :class_name => 'Item', :foreign_key => 'parent_item_id'
has_many :child_items, ->{ order 'position ASC' }, :class_name => 'Item', :foreign_key => 'parent_item_id', :dependent => :destroy
acts_as_list :scope => [:item_id, :parent_type, :parent_item_id]
validate :parent_items_cannot_have_parents

def parent_items_cannot_have_parents
  if child_items.any? && parent_item.present? # THIS IS LINE  #16
    errors.add(:parent_item, "An item with sub-items should live on the root")
  end
end

def parent_item_id=(item_id)
    if new_record?
      self[:parent_item_id] = item_id
    elsif self[:parent_item_id] != ActiveRecord::Base.connection.type_cast(item_id, self.class.columns_hash['parent_item_id'])
      remove_from_list  # IT FAILS HERE LINE # 30
      self[:parent_item_id] = item_id
      send(:add_to_list_bottom)
    end
  end

Трассировка стека:

Item item hierarchy allows a child item to be moved under a different parent
     Failure/Error: if child_item.any? && parent_item.present?

     SystemStackError:
       stack level too deep
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/scoping.rb:79:in `value_for'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activesupport-5.0.7/lib/active_support/per_thread_registry.rb:53:in `value_for'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/scoping.rb:14:in `current_scope'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/scoping/named.rb:25:in `all'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/associations/association.rb:124:in `target_scope'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/associations/association.rb:86:in `scope'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/associations/collection_association.rb:429:in `scope'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/associations/collection_association.rb:348:in `empty?'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/associations/has_many_association.rb:50:in `empty?'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/associations/collection_association.rb:359:in `any?'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/associations/collection_proxy.rb:846:in `any?'
     # ./app/models/item.rb:16:in `parent_items_cannot_have_parents'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activesupport-5.0.7/lib/active_support/callbacks.rb:382:in `block in make_lambda'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activesupport-5.0.7/lib/active_support/callbacks.rb:169:in `block (2 levels) in halting'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activesupport-5.0.7/lib/active_support/callbacks.rb:547:in `block (2 levels) in default_terminator'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activesupport-5.0.7/lib/active_support/callbacks.rb:546:in `catch'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activesupport-5.0.7/lib/active_support/callbacks.rb:546:in `block in default_terminator'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activesupport-5.0.7/lib/active_support/callbacks.rb:170:in `block in halting'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activesupport-5.0.7/lib/active_support/callbacks.rb:454:in `block in call'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activesupport-5.0.7/lib/active_support/callbacks.rb:454:in `each'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activesupport-5.0.7/lib/active_support/callbacks.rb:454:in `call'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activesupport-5.0.7/lib/active_support/callbacks.rb:101:in `__run_callbacks__'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activesupport-5.0.7/lib/active_support/callbacks.rb:750:in `_run_validate_callbacks'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activemodel-5.0.7/lib/active_model/validations.rb:408:in `run_validations!'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activemodel-5.0.7/lib/active_model/validations/callbacks.rb:113:in `block in run_validations!'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activesupport-5.0.7/lib/active_support/callbacks.rb:126:in `call'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activesupport-5.0.7/lib/active_support/callbacks.rb:506:in `block (2 levels) in compile'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activesupport-5.0.7/lib/active_support/callbacks.rb:455:in `call'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activesupport-5.0.7/lib/active_support/callbacks.rb:101:in `__run_callbacks__'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activesupport-5.0.7/lib/active_support/callbacks.rb:750:in `_run_validation_callbacks'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activemodel-5.0.7/lib/active_model/validations/callbacks.rb:113:in `run_validations!'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activemodel-5.0.7/lib/active_model/validations.rb:338:in `valid?'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/validations.rb:65:in `valid?'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/validations.rb:82:in `perform_validations'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/validations.rb:44:in `save'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/attribute_methods/dirty.rb:22:in `save'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/transactions.rb:319:in `block (2 levels) in save'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/transactions.rb:395:in `block in with_transaction_returning_status'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/connection_adapters/abstract/database_statements.rb:230:in `transaction'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/transactions.rb:211:in `transaction'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/transactions.rb:392:in `with_transaction_returning_status'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/transactions.rb:319:in `block in save'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/transactions.rb:334:in `rollback_active_record_state!'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/transactions.rb:318:in `save'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/suppressor.rb:41:in `save'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/acts_as_list-0.9.16/lib/acts_as_list/active_record/acts/list.rb:217:in `set_list_position'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/acts_as_list-0.9.16/lib/acts_as_list/active_record/acts/list.rb:128:in `remove_from_list'
     # ./app/models/item.rb:30:in `parent_item_id='
     # /usr/local/rvm/gems/ruby-2.5.1/gems/acts_as_list-0.9.16/lib/acts_as_list/active_record/acts/list.rb:466:in `block in check_scope'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/acts_as_list-0.9.16/lib/acts_as_list/active_record/acts/list.rb:466:in `each'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/acts_as_list-0.9.16/lib/acts_as_list/active_record/acts/list.rb:466:in `check_scope'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activesupport-5.0.7/lib/active_support/callbacks.rb:382:in `block in make_lambda'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activesupport-5.0.7/lib/active_support/callbacks.rb:150:in `block (2 levels) in halting_and_conditional'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activesupport-5.0.7/lib/active_support/callbacks.rb:770:in `block (2 levels) in deprecated_false_terminator'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activesupport-5.0.7/lib/active_support/callbacks.rb:769:in `catch'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activesupport-5.0.7/lib/active_support/callbacks.rb:769:in `block in deprecated_false_terminator'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activesupport-5.0.7/lib/active_support/callbacks.rb:151:in `block in halting_and_conditional'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activesupport-5.0.7/lib/active_support/callbacks.rb:454:in `block in call'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activesupport-5.0.7/lib/active_support/callbacks.rb:454:in `each'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activesupport-5.0.7/lib/active_support/callbacks.rb:454:in `call'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activesupport-5.0.7/lib/active_support/callbacks.rb:101:in `__run_callbacks__'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activesupport-5.0.7/lib/active_support/callbacks.rb:750:in `_run_update_callbacks'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/callbacks.rb:306:in `_update_record'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/timestamp.rb:81:in `_update_record'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/persistence.rb:548:in `create_or_update'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/callbacks.rb:298:in `block in create_or_update'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activesupport-5.0.7/lib/active_support/callbacks.rb:126:in `call'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activesupport-5.0.7/lib/active_support/callbacks.rb:506:in `block (2 levels) in compile'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activesupport-5.0.7/lib/active_support/callbacks.rb:455:in `call'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activesupport-5.0.7/lib/active_support/callbacks.rb:101:in `__run_callbacks__'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activesupport-5.0.7/lib/active_support/callbacks.rb:750:in `_run_save_callbacks'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/callbacks.rb:298:in `create_or_update'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/persistence.rb:129:in `save'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/validations.rb:44:in `save'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/attribute_methods/dirty.rb:22:in `save'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/transactions.rb:319:in `block (2 levels) in save'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/transactions.rb:395:in `block in with_transaction_returning_status'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/connection_adapters/abstract/database_statements.rb:230:in `transaction'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/transactions.rb:211:in `transaction'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/transactions.rb:392:in `with_transaction_returning_status'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/transactions.rb:319:in `block in save'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/transactions.rb:334:in `rollback_active_record_state!'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/transactions.rb:318:in `save'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/activerecord-5.0.7/lib/active_record/suppressor.rb:41:in `save'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/acts_as_list-0.9.16/lib/acts_as_list/active_record/acts/list.rb:217:in `set_list_position'
     # /usr/local/rvm/gems/ruby-2.5.1/gems/acts_as_list-0.9.16/lib/acts_as_list/active_record/acts/list.rb:128:in `remove_from_list'
     # ./app/models/item.rb:30:in `parent_item_id='

acts_as_list gem использует последнюю версию: 0.9.16


person marimaf    schedule 08.10.2018    source источник
comment
Похоже, у вас происходит глубокая рекурсия. Я знаю, что acts_as_a_list — это жемчужина, поэтому метод remove_from_list — это не ваш код, но просмотр этого может помочь. Возможно, у вас есть циклическая ссылка в базе данных или что-то в этом роде.   -  person    schedule 08.10.2018
comment
Мы должны были встретиться на HackHands, если у вас есть еще вопросы, не стесняйтесь пинговать меня там или здесь.   -  person    schedule 08.10.2018


Ответы (1)


Откат к версии 0.9.5 гема act_as_list решил проблему

person marimaf    schedule 09.10.2018
comment
взгляните на то, что изменилось между этими двумя версиями, и дайте мне знать, если мы сможем это исправить. Я сопровождаю acts_as_list. PR было бы здорово, если у вас есть время. - person Brendon Muir; 19.10.2018
comment
Привет, @BrendonMuir, ошибка произошла при вызове .save, это тебе о чем-нибудь говорит? - person marimaf; 21.10.2018
comment
нет, не совсем :) 0.9.5 уже устарела. Можете ли вы увеличивать оттуда каждую новую версию, пока не получите тестовый сбой, и тогда мы сможем увидеть, что было зафиксировано в этой версии, что могло бы изменить ситуацию для вас. - person Brendon Muir; 22.10.2018
comment
@BrendonMuir Это то, что я сделал, и 0.9.5 была последней, которая сработала. - person marimaf; 24.10.2018
comment
Хорошо, теперь вы можете получить более подробную информацию и посмотреть, какой из коммитов в 0.9.6 сломал вашу установку. github.com/swanandp/acts_as_list/blob/ master/ Я подозреваю, что это могут быть сенсорные изменения. - person Brendon Muir; 25.10.2018