Reputation: 58
I have written a concern to include into data models that will manage our auditable fields in our tables. This successfully overrides delete
, destroy
& update
, but I am not able to catch the delete_all
that executes an undesirable DELETE * FROM ....
module Concerns
module Auditable
extend ActiveSupport::Concern
def auth_id
Authentication.current ? Authentication.current.id : nil
end
def deletion_attributes
{ deleted_at: Time.now.utc, deleted_by: auth_id,
modified_at: Time.now.utc, modified_by: auth_id }
end
def touch
self.created_at ||= Time.now.utc
self.created_by ||= auth_id
self.modified_at = Time.now.utc
self.modified_by = auth_id
end
def deleted?
deleted_at.present?
end
def delete
destroy
end
def destroy
# destroy_associates (still to implement)
update_attributes(deletion_attributes)
end
def undelete
update_attributes(deleted_at: nil, deleted_by: nil,
modified_at: Time.now.utc, modified_by: auth_id)
end
def delete_all
puts "this is never reached"
end
# Set ActiveRecord::Base of caller
def self.included(base)
unless base.ancestors.include?(ActiveRecord::Base)
fail "You can only include this if #{base} extends ActiveRecord::Base"
end
base.class_eval do
default_scope { where("#{table_name}.deleted_at IS NULL") }
before_save :touch
def self.show_deleted
unscoped.where("#{table_name}.deleted_at IS NOT NULL")
end
def delete_all
puts "this is also never reached"
end
end
end
end
end
Upvotes: 1
Views: 817
Reputation: 4322
I believe this is not the right way to override the class methods.
def self.included(base)
unless base.ancestors.include?(ActiveRecord::Base)
fail "You can only include this if #{base} extends ActiveRecord::Base"
end
base.class_eval do
default_scope { where("#{table_name}.deleted_at IS NULL") }
before_save :touch
def self.show_deleted
unscoped.where("#{table_name}.deleted_at IS NOT NULL")
end
def delete_all
puts "this is also never reached"
end
end
end
It works for me this way
def self.included(base)
base.extend(ClassMethods)
end
module ClassMethods
def delete_all
# do nothing
end
end
and make sure to prepend Concerns::Auditable
to override the class methods.
class User < ActiveRecord::Base
prepend Concerns::Auditable
end
You can also use the gem ActsAsParanoid. It does the job for you!
Upvotes: 0
Reputation: 824
What about destroy_all
? Callbacks are not called when using delete_all
from the docs it states "Deletes the records matching conditions without instantiating the records first, and hence not calling the destroy method nor invoking callbacks. This is a single SQL DELETE statement that goes straight to the database, much more efficient than destroy_all."
Upvotes: 1