If you use a method that is not directly defined in the current class, then alias looks for the method in the closest ancestor of the class in which it was executed.
When you include Trashable::InstanceMethods in one of your models, it is inserted at the beginning of this chain of ancestors of this model. Hence the call to destroy! in this model, calls the destroy method on Trashable::InstanceMethods .
If you move def destroy from InstanceMethods to base.class_eval , then it will be defined in the inclusion model directly, and the closest ancestor of this model containing "destroy" will be the corresponding module in ActiveRecord. Therefore call destroy! will invoke SQL DELETE as expected.
See class.ancestors for further study of this behavior.
source share