lib/active_archive/base.rb in active_archive-2.3.0 vs lib/active_archive/base.rb in active_archive-2.4.0

- old
+ new

@@ -3,15 +3,11 @@ def self.included(base) base.extend Methods base.extend Scopes - base.instance_eval do - define_model_callbacks :unarchive - - before_unarchive :unarchive_destroyed_dependent_records - end + base.instance_eval { define_model_callbacks(:unarchive) } end def archived? archivable? ? !!archived_at : destroyed? end @@ -23,11 +19,11 @@ def destroy(force=nil) with_transaction_returning_status do if unarchivable? || should_force_destroy?(force) permanently_delete_records_after { super() } else - destroy_with_permanent_records(force) + destroy_with_active_archive(force) end end end alias_method(:archive, :destroy) @@ -35,13 +31,13 @@ def to_archival I18n.t("active_archive.archival.#{archived? ? :archived : :unarchived}") end - def unarchive(validate=nil) + def unarchive(options=nil) with_transaction_returning_status do - run_callbacks(:unarchive) { set_archived_at(nil, validate) } + (should_unarchive_parent_first?(options) ? unarchival.reverse : unarchival).lazy.each { |r| r.call(options) } self end end alias_method(:unarchive!, :unarchive) @@ -62,15 +58,24 @@ rescue NoMethodError => e # RETURN end end - def destroy_with_permanent_records(force=nil) - run_callbacks(:destroy) { archived? || (new_record? ? save : set_archived_at(Time.now, force)) } + def destroy_with_active_archive(force=nil) + run_callbacks(:destroy) do + (archived? || new_record?) ? save : set_archived_at(Time.now, force) + true + end + archived? ? self : false end + def get_archived_record + record_id = (self.respond_to?(:parent_id) && self.parent_id.present?) ? parent_id : id + self.class.unscoped.find(record_id) + end + def get_dependent_records dependent_records = {} self.class.reflections.lazy.each do |key, reflection| if reflection.options[:dependent] == :destroy next unless records = self.send(key) @@ -87,11 +92,11 @@ return(dependent_records) end def permanently_delete_records(dependent_records) dependent_records.lazy.each do |klass, ids| - ids.each do |id| + ids.lazy.each do |id| record = begin klass.unscoped.find(id) rescue ::ActiveRecord::RecordNotFound next end @@ -106,68 +111,66 @@ dependent_results = block.call permanently_delete_records(dependent_records) if dependent_results return(dependent_results) end - def unarchive_destroyed_dependent_records - self.class.reflections - .lazy - .select { |name, reflection| (reflection.options[:dependent].to_s == 'destroy'.freeze) && reflection.klass.archivable? } - .each do |name, reflection| - cardinality = reflection.macro.to_s.gsub('has_'.freeze, ''.freeze) + def unarchival + [ + ->(_validate) { unarchive_destroyed_dependent_records(_validate) }, + ->(_validate) { run_callbacks(:unarchive) { set_archived_at(nil, _validate) } } + ] + end - if cardinality == 'many'.freeze - records = archived_at.nil? ? send(name).unscoped : send(name).unscoped.where( - [ - "#{reflection.quoted_table_name}.archived_at > ? AND #{reflection.quoted_table_name}.archived_at < ?", - archived_at - ActiveArchive.configuration.dependent_record_window, - archived_at + ActiveArchive.configuration.dependent_record_window - ] - ) - elsif cardinality == 'one'.freeze or cardinality == 'belongs_to'.freeze - self.class.unscoped do - records = [] << send(name) - end - end + def unarchive_destroyed_dependent_records(force = nil) + self.class.reflections.select do |name, reflection| + 'destroy'.freeze == reflection.options[:dependent].to_s && reflection.klass.archivable? + end.each do |name, reflection| + cardinality = reflection.macro.to_s.gsub('has_'.freeze, ''.freeze).to_sym + case cardinality + when :many + records = (archived_at ? set_record_window(send(name), name, reflection) : send(name)) + when :one, :belongs_to + self.class.unscoped { records = [] << send(name) } + end - [records].flatten.compact.lazy.each { |d| d.unarchive } - send(name, :reload) - end + [records].flatten.compact.lazy.each { |d| d.unarchive(force) } + send(name, :reload) + end end def set_archived_at(value, force=nil) return self unless archivable? - record = self.class.unscoped.find(id) + record = get_archived_record record.archived_at = value begin should_ignore_validations?(force) ? record.save(validate: false) : record.save! - - if ::Gem::Version.new(::ActiveRecord::VERSION::STRING) < ::Gem::Version.new('4.2.0'.freeze) - @attributes = record.attributes - @attributes_cache = record.attributes.except(record.class.serialized_attributes.keys) - - if defined?(::ActiveRecord::AttributeMethods::Serialization::Attribute) - serialized_attribute_class = ::ActiveRecord::AttributeMethods::Serialization::Attribute - self.class.serialized_attributes.lazy.each do |key, coder| - @attributes[key] = serialized_attribute_class.new(coder, @attributes[key], :unserialized) if @attributes.key?(key) - end - end - else - @attributes = record.instance_variable_get('@attributes'.freeze) - end + @attributes = record.instance_variable_get('@attributes'.freeze) rescue Exception => e record.destroy raise(e) end end + def set_record_window(request, name, reflection) + send(name).unscope(where: :archived_at) + .where([ + "#{reflection.quoted_table_name}.archived_at > ? AND #{reflection.quoted_table_name}.archived_at < ?", + archived_at - ActiveArchive.configuration.dependent_record_window, + archived_at + ActiveArchive.configuration.dependent_record_window + ]) + end + def should_force_destroy?(force) (Hash === force) ? force[:force] : (:force == force) end def should_ignore_validations?(force) (Hash === force) && (false == force[:validate]) + end + + def should_unarchive_parent_first?(order) + (Hash === order) && (true == order[:reverse]) end end end \ No newline at end of file