undestroyable 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +7 -0
- data/README.md +37 -0
- data/Rakefile +10 -0
- data/lib/undestroyable.rb +21 -0
- data/lib/undestroyable/configuration.rb +142 -0
- data/lib/undestroyable/orm.rb +16 -0
- data/lib/undestroyable/orm/active_record.rb +46 -0
- data/lib/undestroyable/orm/active_record/column.rb +29 -0
- data/lib/undestroyable/orm/active_record/database.rb +64 -0
- data/lib/undestroyable/orm/active_record/dump.rb +84 -0
- data/lib/undestroyable/orm/active_record/table.rb +76 -0
- data/lib/undestroyable/strategies.rb +3 -0
- data/lib/undestroyable/version.rb +3 -0
- metadata +114 -0
data/LICENSE
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
Copyright (C) 2012 Kot-Begemot
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
4
|
+
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
6
|
+
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# Strategies
|
2
|
+
|
3
|
+
* none
|
4
|
+
Deletes record, as with usual destroy method.
|
5
|
+
* column
|
6
|
+
Updates deleted_at column of the record. This is default strategy,
|
7
|
+
if undestroyable is activated for model.
|
8
|
+
* table
|
9
|
+
Move table into separate column
|
10
|
+
* database
|
11
|
+
Move table into separate database
|
12
|
+
|
13
|
+
# Options:
|
14
|
+
|
15
|
+
* table_name
|
16
|
+
Same as model table.
|
17
|
+
* table_suffix
|
18
|
+
Default prefix is: deleted
|
19
|
+
* full_table_name
|
20
|
+
table_prefix + table_name + table_suffix.
|
21
|
+
|
22
|
+
# Simple usage example:
|
23
|
+
|
24
|
+
class Bill < ActiveRecord::Base
|
25
|
+
undestroyable
|
26
|
+
end
|
27
|
+
|
28
|
+
# Complicated usage example:
|
29
|
+
|
30
|
+
class ConceptCat < ActiveRecord::Base
|
31
|
+
undstroyable do
|
32
|
+
startegy :database
|
33
|
+
connection { adapter: "sqlite3", dbfile: ":memory:"}
|
34
|
+
table_name :scrap
|
35
|
+
table_suffix :metalic
|
36
|
+
end
|
37
|
+
end
|
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
module Undestroyable
|
2
|
+
autoload :Configuration, 'undestroyable/configuration'
|
3
|
+
autoload :STRATEGIES, 'undestroyable/strategies'
|
4
|
+
autoload :VERSION, 'undestroyable/version'
|
5
|
+
|
6
|
+
require 'undestroyable/orm'
|
7
|
+
|
8
|
+
module Orm
|
9
|
+
autoload :ActiveRecord, 'undestroyable/orm/active_record'
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.config
|
13
|
+
@config ||= Configuration.new(copy_system: false).tap do |c|
|
14
|
+
def c.orm(orm_type)
|
15
|
+
constant = Undestroyable::Orm
|
16
|
+
loadable = Orm.get_by_key(orm_type)
|
17
|
+
constant.const_defined?(loadable) ? constant.const_get(loadable) : constant.const_missing(loadable)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
module Undestroyable
|
2
|
+
|
3
|
+
class WrongStrategyError < Exception; end
|
4
|
+
class ConnectionIsCompulsaryError < Exception; end
|
5
|
+
|
6
|
+
# Specifies which strategy to use for this configuration.
|
7
|
+
#
|
8
|
+
# Possible options include:
|
9
|
+
# [:startegy]
|
10
|
+
# [:none]
|
11
|
+
# Deletes record, as with usual destroy method. This option may be used as a cancelation
|
12
|
+
# of undestoyable state of record, for STI model as an example.
|
13
|
+
# [:column]
|
14
|
+
# Updates <tt>:deleted_at</tt> column of the record. This is default strategy,
|
15
|
+
# in cafe if undestroyable is specified for model.
|
16
|
+
# [:table]
|
17
|
+
# Move record into separate table.
|
18
|
+
# [:database]
|
19
|
+
# Move table into separate database.
|
20
|
+
# [:dump]
|
21
|
+
# Marshal dump all deleted records into common table table.
|
22
|
+
# [:table_name]
|
23
|
+
# Keep alternative to table name. By default it will equivalent to one used by Model backend.
|
24
|
+
# It is ignored by <tt>:none</tt> and <tt>::column</tt> strategies.
|
25
|
+
# [:table_prefix]
|
26
|
+
# Keep table prefix. If it is set not nil, it will be ignored for table creation. Default is nil.
|
27
|
+
# It is ignored by <tt>:none</tt> and <tt>::column</tt> strategies.
|
28
|
+
# [:table_suffix]
|
29
|
+
# Keep table suffix. If it is set not nil, it will be ignored for table creation. Default is nil.
|
30
|
+
# It is ignored by <tt>:none</tt> and <tt>::column</tt> strategies.
|
31
|
+
# [:full_table_name]
|
32
|
+
# Keep full table name. If this field is not specified it will be generated from
|
33
|
+
# table_name + table_prefix + table_suffix.
|
34
|
+
# It is ignored by <tt>:none</tt> and <tt>::column</tt> strategies.
|
35
|
+
# [:connection]
|
36
|
+
# Keep credetial information for remote database connection.
|
37
|
+
# *NB!* Compulsary for :database strategy, ignored for rest strategies.
|
38
|
+
#
|
39
|
+
# == EXAMPLES
|
40
|
+
#
|
41
|
+
# class ConceptCat < ActiveRecord::Base
|
42
|
+
# undstroyable do
|
43
|
+
# startegy :table
|
44
|
+
# table_name :metalic
|
45
|
+
# table_suffix :scrap
|
46
|
+
# end
|
47
|
+
# end
|
48
|
+
#
|
49
|
+
# class ConceptCat < ActiveRecord::Base
|
50
|
+
# undstroyable do
|
51
|
+
# startegy :database
|
52
|
+
# connection {}
|
53
|
+
# table_name :scrap
|
54
|
+
# end
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# class ConceptCat < ActiveRecord::Base
|
58
|
+
# undstroyable do
|
59
|
+
# startegy :dump
|
60
|
+
# table_name :scrap
|
61
|
+
# end
|
62
|
+
# end
|
63
|
+
#
|
64
|
+
class Configuration
|
65
|
+
|
66
|
+
attr_reader :configuration
|
67
|
+
|
68
|
+
def initialize(opts = {},&block)
|
69
|
+
copy_system = opts[:copy_system].nil? ? true : opts.delete(:copy_system)
|
70
|
+
@configuration ||= (copy_system ? Undestroyable.config.configuration.dup : {})
|
71
|
+
@configuration[:strategy] ||= :column
|
72
|
+
prepare &block if block_given?
|
73
|
+
end
|
74
|
+
|
75
|
+
def prepare &block
|
76
|
+
instance_eval &block
|
77
|
+
raise(::Undestroyable::ConnectionIsCompulsaryError.new "Connection information is compulsary") if database? && connection_settings.blank?
|
78
|
+
end
|
79
|
+
alias_method :setup, :prepare
|
80
|
+
|
81
|
+
#[:strategy, :table_name, :table_suffix, :full_table_name, :connection]
|
82
|
+
|
83
|
+
::Undestroyable::STRATEGIES.each do |strategy|
|
84
|
+
define_method "#{strategy}?" do
|
85
|
+
configuration[:strategy] == strategy
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# Allows to access <tt>configuration</tt> values via provided keys.
|
90
|
+
# Example:
|
91
|
+
#
|
92
|
+
# c = Undestroyable.config
|
93
|
+
# c[:strategy] # => :column
|
94
|
+
def [](option_name)
|
95
|
+
# :full_table_name will be generated on first request
|
96
|
+
generate_full_name if option_name == :full_table_name && !configuration[:full_table_name]
|
97
|
+
configuration[option_name]
|
98
|
+
end
|
99
|
+
|
100
|
+
def strategy(shrtkey)
|
101
|
+
raise WrongStrategyError.new(%Q{Such strategy "#{shrtkey}" does not exists.}) unless ::Undestroyable::STRATEGIES.include? shrtkey.to_sym
|
102
|
+
table_name('dump') if shrtkey.to_sym == :dump && !@configuration[:table_name]
|
103
|
+
@configuration[:strategy] = shrtkey.to_sym
|
104
|
+
end
|
105
|
+
|
106
|
+
def table_name(alternative_table_name)
|
107
|
+
@configuration[:table_name] = alternative_table_name
|
108
|
+
end
|
109
|
+
|
110
|
+
def table_prefix(alternative_table_prefix)
|
111
|
+
@configuration[:table_prefix] = alternative_table_prefix
|
112
|
+
end
|
113
|
+
|
114
|
+
def table_suffix(alternative_table_suffix)
|
115
|
+
@configuration[:table_suffix] = alternative_table_suffix
|
116
|
+
end
|
117
|
+
|
118
|
+
def full_table_name(alternative_full_table_name)
|
119
|
+
@configuration[:full_table_name] = alternative_full_table_name
|
120
|
+
end
|
121
|
+
|
122
|
+
def connection(alternative_connection)
|
123
|
+
@configuration[:connection] = alternative_connection
|
124
|
+
end
|
125
|
+
|
126
|
+
def connection_settings
|
127
|
+
@configuration[:connection]
|
128
|
+
end
|
129
|
+
|
130
|
+
private
|
131
|
+
|
132
|
+
def generate_full_name
|
133
|
+
if @configuration[:table_prefix] || @configuration[:table_name] || @configuration[:table_suffix]
|
134
|
+
table_name = "#{@configuration[:table_prefix].to_s}_" if @configuration[:table_prefix]
|
135
|
+
(table_name ||= '') << @configuration[:table_name].to_s
|
136
|
+
table_name << "_#{@configuration[:table_suffix].to_s}" if @configuration[:table_suffix]
|
137
|
+
@configuration[:full_table_name] = table_name.to_sym
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Undestroyable
|
2
|
+
module Orm
|
3
|
+
SUPPORTED = %(ActiveRecord).freeze
|
4
|
+
|
5
|
+
class UnexisingOrmError < RuntimeError; end
|
6
|
+
|
7
|
+
def Orm.get_by_key(key)
|
8
|
+
case key.to_sym
|
9
|
+
when :active_record
|
10
|
+
'ActiveRecord'
|
11
|
+
else
|
12
|
+
raise UnexisingOrmError.new "No orm matching: :#{key.to_s}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
module Undestroyable
|
4
|
+
module Orm
|
5
|
+
module ActiveRecord
|
6
|
+
autoload :Column, 'undestroyable/orm/active_record/column'
|
7
|
+
autoload :Table, 'undestroyable/orm/active_record/table'
|
8
|
+
autoload :Database, 'undestroyable/orm/active_record/database'
|
9
|
+
autoload :Dump, 'undestroyable/orm/active_record/dump'
|
10
|
+
|
11
|
+
def self.included(base)
|
12
|
+
base.instance_eval { alias_method :destroy!, :destroy }
|
13
|
+
base.extend ClassMethods
|
14
|
+
end
|
15
|
+
|
16
|
+
module ClassMethods
|
17
|
+
def undestroyable &block
|
18
|
+
undestr_config(&block) unless @undestr_config
|
19
|
+
undestr_config.table_name(table_name) unless undestr_config[:table_name]
|
20
|
+
undestr_include_startegy
|
21
|
+
undestr_config
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
|
26
|
+
def undestr_include_startegy
|
27
|
+
undestr_strategy = undestr_config[:strategy]
|
28
|
+
if Undestroyable::STRATEGIES.include? undestr_strategy
|
29
|
+
if undestr_config.none?
|
30
|
+
#nothing should happen for this strategy.
|
31
|
+
else
|
32
|
+
include "Undestroyable::Orm::ActiveRecord::#{undestr_strategy.to_s.classify}".constantize
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Keeps undestroyable configuration for class.
|
38
|
+
def undestr_config &block
|
39
|
+
@undestr_config ||= Undestroyable::Configuration.new(&block)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
ActiveRecord::Base.send :include, Undestroyable::Orm::ActiveRecord
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Undestroyable
|
2
|
+
module Orm
|
3
|
+
module ActiveRecord
|
4
|
+
# <tt>:column</tt> strategy is the easiest among the rest. It just updates <tt>:deleted_at</tt> column
|
5
|
+
# of the record, and set default scope conditions, to prevent its returning by default. Despite the record
|
6
|
+
# is actually just updated, no update callback will be triggered.
|
7
|
+
#
|
8
|
+
# == Example
|
9
|
+
#
|
10
|
+
# class ConceptCat < ActiveRecord::Base
|
11
|
+
# undstroyable do
|
12
|
+
# startegy :column
|
13
|
+
# end
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
module Column
|
17
|
+
def self.included(base)
|
18
|
+
base.send :default_scope, base.where('deleted_at IS NULL')
|
19
|
+
end
|
20
|
+
|
21
|
+
def destroy
|
22
|
+
run_callbacks :destroy do
|
23
|
+
update_column :deleted_at, Time.now
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Undestroyable
|
2
|
+
module Orm
|
3
|
+
module ActiveRecord
|
4
|
+
# <tt>:database</tt> strategy will save any deleted record within remote database. <tt>:connection</tt> option
|
5
|
+
# *is required*. By default, it will use same naming as a actual table. In order to change the table name,
|
6
|
+
# following options can be specified within configuration:
|
7
|
+
#
|
8
|
+
# [:table_name]
|
9
|
+
# Keep alternative to table name. By default it will equivalent to one used by Model backend.
|
10
|
+
# [:table_prefix]
|
11
|
+
# Keep table prefix. If it is set not nil, it will be ignored for table creation. Default is nil.
|
12
|
+
# [:table_suffix]
|
13
|
+
# Keep table suffix. If it is set not nil, it will be ignored for table creation. Default is nil.
|
14
|
+
# [:full_table_name]
|
15
|
+
# Keep full table name. If this field is not specified it will be generated from
|
16
|
+
# table_name + table_prefix + table_suffix.
|
17
|
+
#
|
18
|
+
# == Example
|
19
|
+
#
|
20
|
+
# class ConceptCat < ActiveRecord::Base
|
21
|
+
# undstroyable do
|
22
|
+
# startegy :database
|
23
|
+
# connection { adapter: "sqlite3", dbfile: ":memory:"}
|
24
|
+
# table_name :scrap
|
25
|
+
# table_suffix :metalic
|
26
|
+
# end
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
module Database
|
30
|
+
|
31
|
+
def self.included(base)
|
32
|
+
base.send :include, Table
|
33
|
+
base.send :include, InstanceMethods
|
34
|
+
base.extend ClassMethods
|
35
|
+
end
|
36
|
+
|
37
|
+
module ClassMethods
|
38
|
+
# Because undest_arel_table is just being ignored over there....
|
39
|
+
def undest_mirror
|
40
|
+
@undest_mirror ||= begin
|
41
|
+
copy = self.dup
|
42
|
+
copy.table_name = undestr_config[:full_table_name]
|
43
|
+
def copy.name; undestr_config[:full_table_name].to_s.classify; end
|
44
|
+
copy.establish_connection undestr_config[:connection]
|
45
|
+
copy
|
46
|
+
end
|
47
|
+
end
|
48
|
+
protected :undest_mirror
|
49
|
+
end
|
50
|
+
|
51
|
+
module InstanceMethods
|
52
|
+
def destroy
|
53
|
+
run_callbacks :destroy do
|
54
|
+
deleted_attributes = undest_compile_insert_attributes
|
55
|
+
deleted_attributes << [self.class.undest_arel_table['deleted_at'], Time.now.utc] if self.class.send(:undest_mirror).columns_hash['deleted_at']
|
56
|
+
self.class.undest_relation.insert deleted_attributes
|
57
|
+
destroy!
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module Undestroyable
|
2
|
+
module Orm
|
3
|
+
module ActiveRecord
|
4
|
+
# <tt>:dump</tt> strategy is the most simple one. It requires only one table for whole project to save a data
|
5
|
+
# in it. What it does internally, is just marshal dump an object and save it into specific table. That table
|
6
|
+
# should have predefined format. That allows to keep an objects of different class within same table. In order
|
7
|
+
# to change the table name, following options can be specified within configuration:
|
8
|
+
#
|
9
|
+
# [:table_name]
|
10
|
+
# Keep alternative to table name. By default it will equivalent to one used by Model backend.
|
11
|
+
# [:table_prefix]
|
12
|
+
# Keep table prefix. If it is set not nil, it will be ignored for table creation. Default is nil.
|
13
|
+
# [:table_suffix]
|
14
|
+
# Keep table suffix. If it is set not nil, it will be ignored for table creation. Default is nil.
|
15
|
+
# [:full_table_name]
|
16
|
+
# Keep full table name. If this field is not specified it will be generated from
|
17
|
+
# table_name + table_prefix + table_suffix.
|
18
|
+
#
|
19
|
+
# == Table structure
|
20
|
+
#
|
21
|
+
# [:dump]
|
22
|
+
# This is a text column that keepes deleted object.
|
23
|
+
# [:deleted_at]
|
24
|
+
# This column keeps a time of the recodr deletion. Time is saved as UTC.
|
25
|
+
#
|
26
|
+
# == Example
|
27
|
+
#
|
28
|
+
# Undestroyable.config do
|
29
|
+
# strategy :dump
|
30
|
+
# full_table_name :dump
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# class Order < ActiveRecord::Base
|
34
|
+
# undestroyable
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# *or*
|
38
|
+
#
|
39
|
+
# class Invoice < ActiveRecord::Base
|
40
|
+
# undestroyable do
|
41
|
+
# strategy :dump
|
42
|
+
# table_suffix :dump
|
43
|
+
# end
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# +dump+ table will contain an order as an object.
|
47
|
+
#
|
48
|
+
# *NB!* Check out Marshal class in Ruby, for how to make this text back to object.
|
49
|
+
module Dump
|
50
|
+
|
51
|
+
def self.included(base)
|
52
|
+
base.send :include, InstanceMethods
|
53
|
+
base.extend ClassMethods
|
54
|
+
end
|
55
|
+
|
56
|
+
module ClassMethods
|
57
|
+
# Because undest_arel_table is just being ignored over there....
|
58
|
+
def undest_mirror
|
59
|
+
@undest_mirror ||= begin
|
60
|
+
dump_table = ::Undestroyable::Orm::ActiveRecord::DumpTable
|
61
|
+
dump_table.table_name = undestr_config[:full_table_name]
|
62
|
+
dump_table.establish_connection(undestr_config[:connection]) unless undestr_config[:connection].blank?
|
63
|
+
dump_table
|
64
|
+
end
|
65
|
+
end
|
66
|
+
protected :undest_mirror
|
67
|
+
end
|
68
|
+
|
69
|
+
module InstanceMethods
|
70
|
+
def destroy
|
71
|
+
run_callbacks :destroy do
|
72
|
+
dump_attributes = {dump: Marshal::dump(self)}
|
73
|
+
dump_attributes.merge!(deleted_at: Time.now.utc) if self.class.send(:undest_mirror).columns_hash['deleted_at']
|
74
|
+
self.class.send(:undest_mirror).create(dump_attributes)
|
75
|
+
destroy!
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
class DumpTable < ::ActiveRecord::Base; end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Undestroyable
|
2
|
+
module Orm
|
3
|
+
module ActiveRecord
|
4
|
+
# <tt>:table</tt> strategy will save any deleted record within separate table. By default, it will use
|
5
|
+
# same naming as a actual table. In order to change the table name, following options can be specified
|
6
|
+
# within configuration:
|
7
|
+
#
|
8
|
+
# [:table_name]
|
9
|
+
# Keep alternative to table name. By default it will equivalent to one used by Model backend.
|
10
|
+
# [:table_prefix]
|
11
|
+
# Keep table prefix. If it is set not nil, it will be ignored for table creation. Default is nil.
|
12
|
+
# [:table_suffix]
|
13
|
+
# Keep table suffix. If it is set not nil, it will be ignored for table creation. Default is nil.
|
14
|
+
# [:full_table_name]
|
15
|
+
# Keep full table name. If this field is not specified it will be generated from
|
16
|
+
# table_name + table_prefix + table_suffix.
|
17
|
+
#
|
18
|
+
# == Example
|
19
|
+
#
|
20
|
+
# class ConceptCat < ActiveRecord::Base
|
21
|
+
# undstroyable do
|
22
|
+
# startegy :database
|
23
|
+
# connection { adapter: "sqlite3", dbfile: ":memory:"}
|
24
|
+
# table_name :scrap
|
25
|
+
# table_suffix :metalic
|
26
|
+
# end
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
module Table
|
30
|
+
def self.included(base)
|
31
|
+
base.send :include, InstanceMethods
|
32
|
+
base.extend ClassMethods
|
33
|
+
end
|
34
|
+
|
35
|
+
module ClassMethods
|
36
|
+
def undest_arel_table
|
37
|
+
@undest_table ||= ::Arel::Table.new(undestr_config[:full_table_name], self)
|
38
|
+
end
|
39
|
+
|
40
|
+
def undest_relation
|
41
|
+
@undest_relation ||= ::ActiveRecord::Relation.new(undest_mirror, undest_arel_table)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Because undest_arel_table is just being ignored over there....
|
45
|
+
def undest_mirror
|
46
|
+
@undest_mirror ||= begin
|
47
|
+
copy = self.dup
|
48
|
+
copy.table_name = undestr_config[:full_table_name]
|
49
|
+
copy
|
50
|
+
end
|
51
|
+
end
|
52
|
+
protected :undest_mirror
|
53
|
+
end
|
54
|
+
|
55
|
+
module InstanceMethods
|
56
|
+
def destroy
|
57
|
+
run_callbacks :destroy do
|
58
|
+
deleted_attributes = undest_compile_insert_attributes
|
59
|
+
deleted_attributes << [self.class.undest_arel_table['deleted_at'], Time.now.utc]
|
60
|
+
self.class.undest_relation.insert deleted_attributes
|
61
|
+
destroy!
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def undest_compile_insert_attributes
|
66
|
+
attributes.map do |key, value|
|
67
|
+
[self.class.undest_arel_table[key], value]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
protected :undest_compile_insert_attributes
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
metadata
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: undestroyable
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- E-Max
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-05-02 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activesupport
|
16
|
+
requirement: &78020570 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 3.0.0
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *78020570
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: activerecord
|
27
|
+
requirement: &78020340 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 3.0.0
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *78020340
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: sqlite3
|
38
|
+
requirement: &78020140 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *78020140
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: database_cleaner
|
49
|
+
requirement: &78019870 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.7.2
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *78019870
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: ruby-debug19
|
60
|
+
requirement: &78019660 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *78019660
|
69
|
+
description: An aim or this gem is to provide an agile and comfortable way for Ruby
|
70
|
+
developers to get rid of unnecessary data within their project databases.
|
71
|
+
email:
|
72
|
+
- emax@studentify.nl
|
73
|
+
executables: []
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- lib/undestroyable/version.rb
|
78
|
+
- lib/undestroyable/orm/active_record.rb
|
79
|
+
- lib/undestroyable/orm/active_record/dump.rb
|
80
|
+
- lib/undestroyable/orm/active_record/database.rb
|
81
|
+
- lib/undestroyable/orm/active_record/column.rb
|
82
|
+
- lib/undestroyable/orm/active_record/table.rb
|
83
|
+
- lib/undestroyable/orm.rb
|
84
|
+
- lib/undestroyable/strategies.rb
|
85
|
+
- lib/undestroyable/configuration.rb
|
86
|
+
- lib/undestroyable.rb
|
87
|
+
- LICENSE
|
88
|
+
- README.md
|
89
|
+
- Rakefile
|
90
|
+
homepage: http://github.com/kot-begemot/undestroyable
|
91
|
+
licenses: []
|
92
|
+
post_install_message:
|
93
|
+
rdoc_options: []
|
94
|
+
require_paths:
|
95
|
+
- lib
|
96
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
|
+
none: false
|
104
|
+
requirements:
|
105
|
+
- - ! '>='
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: 1.3.6
|
108
|
+
requirements: []
|
109
|
+
rubyforge_project: undestroyable
|
110
|
+
rubygems_version: 1.8.10
|
111
|
+
signing_key:
|
112
|
+
specification_version: 3
|
113
|
+
summary: Undestroyable gem
|
114
|
+
test_files: []
|