Last active
August 29, 2015 14:14
-
-
Save YoshitsuguFujii/e86d1f208a594ae4effa to your computer and use it in GitHub Desktop.
real delete when no relation (dependent on acts_as_pranoid)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# lib/active_record/real_delete_discreetly.rb | |
module RealDeleteDiscreetly | |
extend ActiveSupport::Concern | |
def delete_discreetly | |
relation_exist = false | |
self.class.confirm_relations.each do |confirm_relation| | |
if destroyed_by_association | |
if destroyed_by_association.active_record == confirm_relation.to_s.classify.constantize | |
relation_exist = false | |
break | |
end | |
else | |
if reflection = self.class.reflections[confirm_relation].presence | |
send_method = case reflection.macro | |
when :has_many | |
:exists? | |
else | |
:present? | |
end | |
if send(confirm_relation).send(send_method) | |
relation_exist = true | |
break | |
end | |
else | |
raise ArgumentError, "#{confirm_relation} is not Reflection" | |
end | |
end | |
end | |
unless relation_exist | |
self.class.delete_all!(self.class.primary_key.to_sym => id) | |
end | |
end | |
module ClassMethods | |
def real_delete_discreetly(options = {}) | |
class_attribute :confirm_relations | |
self.confirm_relations = options.delete(:confirm_relations) | |
acts_as_paranoid options | |
after_destroy :delete_discreetly | |
end | |
end | |
end | |
# spec support | |
shared_examples_for 'real delete discreetly' do |opts| | |
let(:base_instance) { opts[:base_instance] } | |
let(:confirm_relations) { opts[:confirm_relations] } | |
let(:paranoid_column) { opts[:paranoid_column] || :delete_flag } | |
let(:paranoid_column_type) { opts[:paranoid_column_type] || :boolean } | |
before do | |
@model = base_instance.dup | |
@model.save | |
case paranoid_column_type.to_sym | |
when :boolean | |
@from = false | |
@to = true | |
else | |
time = Time.now | |
Time.stub(:now).and_return(time) | |
@from = nil | |
@to = time | |
end | |
end | |
context 'relation exists' do | |
before do | |
confirm_relation = confirm_relations.first | |
case @model.class.reflections[confirm_relation].macro | |
when :has_many | |
@model.send(confirm_relation).send(:build) | |
else | |
@model.send("build_#{confirm_relation}") | |
end | |
end | |
it 'soft deleted' do | |
expect { @model.destroy }.to change { @model.send(paranoid_column) }.from(@from).to(@to) | |
end | |
it 'not real deleted' do | |
expect { @model.destroy }.to change(@model.class.unscoped, :count).by(0) | |
end | |
end | |
context 'when relation not exists' do | |
it 'real deleted' do | |
expect { @model.destroy }.to change(@model.class.unscoped, :count).by(-1) | |
end | |
end | |
end | |
# Usage | |
## in Model | |
class UserProfile < ActiveRecord::Base | |
belongs_to :user | |
real_delete_discreetly column: :del_flg, column_type: 'boolean', confirm_relations: [:user] | |
end | |
## rspec | |
require 'rails_helper' | |
RSpec.describe UserProfile, type: :model do | |
include_examples 'real delete discreetly', | |
base_instance: UserProfile.create(user_id: nil_or_exist_id), | |
confirm_relations: [:user] | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment