Как получить рельсы и activerecord для управления состоянием через ассоциацию

У меня есть приложение с функциями архива, позволяющее пользователям восстанавливать объекты после их удаления.

Основные функциональные возможности были реализованы следующим образом:

class Contact < ActiveRecord::Base
 belongs_to :organisation

 default_scope { where(:archived => false) }

 def self.archived
 unscoped.where(:archived => true)
 end

 def archive
 update(:archived => true)
 end

 def restore
 update(:archived => false)
 end
end

class Organisation < ActiveRecord::Base
 has_many :contacts

 default_scope { where(:archived => false) }

 def self.archived
 unscoped.where(:archived => true)
 end

 def archive
 update(:archived => true)
 end

 def restore
 update(:archived => false)
 end
end

Тем не менее, поддержка должна быть добавлена для "каскадирования" archive и действий restore через ассоциацию has_many belongs_to.

Необходимые правила заключаются в следующем:

  • Когда контакт архивируется: если контакт является последним "активным" контактом, связанным с организацией, тогда организация также должна быть заархивирована.
  • Когда контакт восстанавливается: если связанная организация архивируется, она также должна быть восстановлена, не восстанавливая никаких других архивных контактов, связанных с организацией.
  • Когда организация архивируется: она должна архивировать все связанные "активные" контакты.
  • Когда организация восстанавливается: она должна восстанавливать все архивированные контакты.

Как это должно быть достигнуто?

1 ответ

class Contact < ActiveRecord::Base
 belongs_to :organisation

 default_scope { where(:archived => false) }

 def self.archived
 unscoped.where(:archived => true)
 end

 def archive
 update(:archived => true)
 organisation.archive(all: false) if organisation.contacts.archived.count == organisation.contacts.count
 end

 def restore
 update(:archived => false)
 organisation.restore(all: false) if organisation.archived
 end
end

class Organisation < ActiveRecord::Base
 has_many :contacts

 default_scope { where(:archived => false) }

 def self.archived
 unscoped.where(:archived => true)
 end

 def archive(all: true)
 update(:archived => true)
 contacts.update_all(:archived => true) if all
 end

 def restore(all: true)
 update(:archived => false)
 contacts.update_all(:archived => false) if all
 end
end

licensed under cc by-sa 3.0 with attribution.