# ActsAsArchived # # Implements the dumb archived pattern # An archived object should not be displayed on index screens, or any related resource's #new pages # effective_select (from the effective_bootstrap gem) is aware of this concern, and calls .unarchived and .archived appropriately when passed an ActiveRecord relation # Use the cascade argument to cascade archived changes to any has_manys # # class Thing < ApplicationRecord # has_many :comments # acts_as_archivable cascade: :comments # end # Each controller needs its own archive and unarchive action. # To simplify this, use the following route concern. # # In your routes.rb: # # Rails.application.routes.draw do # acts_as_archived # # resource :things, concern: :acts_as_archived # resource :comments, concern: :acts_as_archived # end # # and include Effective::CrudController in your resource controller module ActsAsArchived extend ActiveSupport::Concern module ActiveRecord def acts_as_archived(cascade: []) cascade = Array(cascade).compact if cascade.any? { |obj| !obj.kind_of?(Symbol) } raise 'expected cascade to be an Array of has_many symbols' end @acts_as_archived_options = { cascade: cascade } include ::ActsAsArchived end end module CanCan def acts_as_archived(klass) raise "klass does not implement acts_as_archived" unless klass.acts_as_archived? can(:archive, klass) { |obj| !obj.archived? } can(:unarchive, klass) { |obj| obj.archived? } end end module RoutesConcern def acts_as_archived concern :acts_as_archived do post :archive, on: :member post :unarchive, on: :member end end end included do scope :archived, -> { where(archived: true) } scope :unarchived, -> { where(archived: false) } effective_resource do archived :boolean, permitted: false end acts_as_archived_options = @acts_as_archived_options self.send(:define_method, :acts_as_archived_options) { acts_as_archived_options } end module ClassMethods def acts_as_archived?; true; end end # Instance methods def archive! transaction do update!(archived: true) # Runs validations acts_as_archived_options[:cascade].each { |obj| public_send(obj).update_all(archived: true) } end end def unarchive! transaction do update_column(:archived, false) # Does not run validations acts_as_archived_options[:cascade].each { |obj| public_send(obj).update_all(archived: false) } end end def destroy archive! end end