Skip to content

Instantly share code, notes, and snippets.

@TimFletcher
Created November 7, 2012 17:05
Show Gist options
  • Save TimFletcher/4032984 to your computer and use it in GitHub Desktop.
Save TimFletcher/4032984 to your computer and use it in GitHub Desktop.
Trashable 'concern' for Rails models
# db/migrate/20120625030355_add_deleted_at_to_user.rb
class AddDeletedAtToUser < ActiveRecord::Migration
def change
add_column :users, :deleted_at, :time
end
end
# config/application.rb
module YourApp
class Application < Rails::Application
config.autoload_paths += %W(
#{config.root}/lib
#{config.root}/app/controllers/concerns
#{config.root}/app/models/concerns
)
end
# app/models/concerns/trashable.rb
module Trashable
extend ActiveSupport::Concern
included do
default_scope where(deleted_at: nil)
end
module ClassMethods
def trashed
self.unscoped.where(self.arel_table[:deleted_at].not_eq(nil))
end
end
def trash
run_callbacks :destroy do
update_column :deleted_at, Time.now
end
end
def recover
# update_column not appropriate here as it uses the default scope
update_attribute :deleted_at, nil
end
end
# app/models/user.rb
class User < ActiveRecord::Base
include Trashable
end
@nativestranger
Copy link

I like to override #destroy like this so that dependent models are protected during 'dependent: :destroy' callbacks.

def destroy
  self.trash
end

For example, this way, the comments of a user will be trashed rather than destroyed in a situation like the one below.

class User < ApplicationRecord
  include Trashable
  has_many :comments, dependent: :destroy
end

class Comment < ApplicationRecord
  include Trashable
  belongs_to :user
end

Now it'd be nice if #recover could handle recovering trashed dependents.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment