deactivatable 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +1 -0
- data/README.rdoc +15 -0
- data/VERSION +1 -1
- data/lib/deactivatable.rb +25 -8
- data/test/deactivatable_item.rb +2 -3
- data/test/deactivatable_test.rb +88 -29
- metadata +2 -2
data/.gitignore
CHANGED
data/README.rdoc
CHANGED
@@ -1,10 +1,25 @@
|
|
1
1
|
= deactivatable
|
2
2
|
|
3
|
+
== Description
|
3
4
|
Deactivatable provides methods and a default_scope to allow ActiveRecord objects to be deactivated instead of deleted.
|
4
5
|
This is useful if an object needs to be removed from general use, but it's data needs to be retained.
|
5
6
|
Additionally, Deactivatable provides the ability to specify dependencies which also need to be deactivated.
|
6
7
|
Deactivation is determined by populating a deactivated_at field with the date time at which deactivation happened.
|
7
8
|
|
9
|
+
== Install
|
10
|
+
The deactivatable gem is hosted on GemCutter (http://gemcutter.org)
|
11
|
+
gem install deactivatable
|
12
|
+
OR
|
13
|
+
config.gem 'deactivatable', :source => 'http://gemcutter.org'
|
14
|
+
|
15
|
+
== Usage
|
16
|
+
* Add a deactivated_at datetime field to any table you want to be deactivatable
|
17
|
+
add_column :table_name, :deactivated_at, :datetime
|
18
|
+
* Add the acts_as_deactivatable call to any class that should be deactivatable
|
19
|
+
Options
|
20
|
+
:dependencies - A list of symbols specifying any associations that are also deactivatable. (The dependent association must separately be defined with acts_as_deactivatable).
|
21
|
+
:auto_configure_dependencies - true or false (default). If set to true, any association defined as :dependent => :destroy or :dependent => :delete_all will be added to the list of dependencies to deactivate. NOTE: This call must occur after your dependency definitions to work properly.
|
22
|
+
|
8
23
|
== Note on Patches/Pull Requests
|
9
24
|
|
10
25
|
* Fork the project.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.2
|
data/lib/deactivatable.rb
CHANGED
@@ -11,7 +11,8 @@ module ActiveRecord
|
|
11
11
|
# Define the calling class as being deactivatable.
|
12
12
|
# A call to this will set the default scope of the object to look for deactivated_at = nil.
|
13
13
|
# Options
|
14
|
-
#
|
14
|
+
# :dependencies - A list of symbols specifying any associations that are also deactivatable. (The dependent association must separately be defined with acts_as_deactivatable).
|
15
|
+
# :auto_configure_dependencies - true or false (default). If set to true, any association defined as :dependent => :destroy or :dependent => :delete_all will be added to the list of dependencies to deactivate. NOTE: This call must occur after your dependency definitions to work properly.
|
15
16
|
#
|
16
17
|
def acts_as_deactivatable(options={})
|
17
18
|
extend ActiveRecord::Acts::Deactivatable::ClassMethods
|
@@ -20,6 +21,7 @@ module ActiveRecord
|
|
20
21
|
default_scope :conditions => {:deactivated_at => nil}
|
21
22
|
|
22
23
|
@deactivatable_options = options
|
24
|
+
setup_autoconfigured_dependencies if @deactivatable_options[:auto_configure_dependencies]
|
23
25
|
end
|
24
26
|
|
25
27
|
end
|
@@ -30,10 +32,6 @@ module ActiveRecord
|
|
30
32
|
@deactivatable_options || {}
|
31
33
|
end
|
32
34
|
|
33
|
-
def deactivated_dependencies
|
34
|
-
@deactivated_dependencies ||= []
|
35
|
-
end
|
36
|
-
|
37
35
|
# Yields to a block, executing that block after removing the deactivated_at scope.
|
38
36
|
#
|
39
37
|
def with_deactivated_objects_scope
|
@@ -43,8 +41,26 @@ module ActiveRecord
|
|
43
41
|
end
|
44
42
|
end
|
45
43
|
end
|
44
|
+
|
45
|
+
private
|
46
|
+
# Scan the reflection associations defined on the current class,
|
47
|
+
# if the :dependent option is set to :destroy or :delete_all then add that reflection to the list of dependencies to be deactivated.
|
48
|
+
#
|
49
|
+
def setup_autoconfigured_dependencies
|
50
|
+
self.reflections.each_key { |reflection_name| setup_auto_configured_dependency(reflection_name) }
|
51
|
+
end
|
52
|
+
|
53
|
+
def setup_auto_configured_dependency(reflection_name)
|
54
|
+
@deactivatable_options[:dependencies] ||= []
|
55
|
+
reflection = self.reflections[reflection_name]
|
56
|
+
|
57
|
+
if [:destroy, :delete_all].include?(reflection.options[:dependent])
|
58
|
+
@deactivatable_options[:dependencies] << reflection_name
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
46
62
|
end
|
47
|
-
|
63
|
+
|
48
64
|
module InstanceMethods
|
49
65
|
|
50
66
|
# Deactivate this object, and any associated objects as specified at definition time.
|
@@ -97,8 +113,9 @@ module ActiveRecord
|
|
97
113
|
#
|
98
114
|
def execute_on_dependency(dependency_name, method)
|
99
115
|
self.class.reflections[dependency_name].klass.send(:with_exclusive_scope) do
|
100
|
-
dependency = self.__send__(dependency_name)
|
101
|
-
|
116
|
+
if dependency = self.__send__(dependency_name)
|
117
|
+
dependency.respond_to?(:map) ? dependency.map(&method) : dependency.__send__(method)
|
118
|
+
end
|
102
119
|
end
|
103
120
|
end
|
104
121
|
|
data/test/deactivatable_item.rb
CHANGED
data/test/deactivatable_test.rb
CHANGED
@@ -2,6 +2,38 @@ require 'test_helper'
|
|
2
2
|
|
3
3
|
class DeactivatableTest < Test::Unit::TestCase
|
4
4
|
|
5
|
+
|
6
|
+
def self.should_deactivate_and_reactivate_dependencies
|
7
|
+
context "on a call to deactivate!" do
|
8
|
+
setup do
|
9
|
+
@item.deactivate!
|
10
|
+
end
|
11
|
+
|
12
|
+
should "render dependency unfindable" do
|
13
|
+
@dependencies.each { |dependency| assert !DeactivatableDependency.exists?(dependency.id) }
|
14
|
+
end
|
15
|
+
|
16
|
+
should "set deactivate on dependency post" do
|
17
|
+
DeactivatableDependency.send(:with_exclusive_scope) do
|
18
|
+
@dependencies.map(&:reload)
|
19
|
+
@dependencies.each {|dependency| assert_not_nil(dependency.deactivated_at) }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context "when reactivated" do
|
24
|
+
setup do
|
25
|
+
@item.activate!
|
26
|
+
end
|
27
|
+
|
28
|
+
should "reactivate all dependencies" do
|
29
|
+
@dependencies.each { |dependency| assert(DeactivatableDependency.exists?(dependency.id)) }
|
30
|
+
end
|
31
|
+
end #when reactivated
|
32
|
+
|
33
|
+
end #on a call to deactivate!
|
34
|
+
end
|
35
|
+
|
36
|
+
|
5
37
|
context "An inactive item, @item" do
|
6
38
|
setup do
|
7
39
|
@inactive_item = DeactivatableItem.new
|
@@ -57,38 +89,65 @@ class DeactivatableTest < Test::Unit::TestCase
|
|
57
89
|
|
58
90
|
context "with dependencies, @dependencies" do
|
59
91
|
setup do
|
60
|
-
@
|
61
|
-
@item.
|
92
|
+
@item.class.instance_eval { has_many :deactivatable_dependencies }
|
93
|
+
@item.class.instance_eval { acts_as_deactivatable :dependencies => [:deactivatable_dependencies] }
|
94
|
+
create_item_dependencies
|
62
95
|
end
|
63
96
|
|
64
|
-
|
65
|
-
setup do
|
66
|
-
@item.deactivate!
|
67
|
-
end
|
68
|
-
|
69
|
-
should "render dependency unfindable" do
|
70
|
-
@dependencies.each { |dependency| assert !DeactivatableDependency.exists?(dependency.id) }
|
71
|
-
end
|
72
|
-
|
73
|
-
should "set deactivate on dependency post" do
|
74
|
-
DeactivatableDependency.send(:with_exclusive_scope) do
|
75
|
-
@dependencies.map(&:reload)
|
76
|
-
@dependencies.each {|dependency| assert_not_nil(dependency.deactivated_at) }
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
context "when reactivated" do
|
81
|
-
setup do
|
82
|
-
@item.activate!
|
83
|
-
end
|
84
|
-
|
85
|
-
should "reactivate all dependencies" do
|
86
|
-
@dependencies.each { |dependency| assert(DeactivatableDependency.exists?(dependency.id)) }
|
87
|
-
end
|
88
|
-
end #when reactivated
|
89
|
-
|
90
|
-
end #on a call to deactivate!
|
97
|
+
should_deactivate_and_reactivate_dependencies
|
91
98
|
end #with dependencies, @dependencies
|
99
|
+
|
100
|
+
context "with dependencies, @dependencies, that are :dependent => :destroy, and with auto_configure_dependencies => true" do
|
101
|
+
setup do
|
102
|
+
@item.class.instance_eval { has_many :deactivatable_dependencies, :dependent => :destroy }
|
103
|
+
@item.class.instance_eval { acts_as_deactivatable :auto_configure_dependencies => true }
|
104
|
+
create_item_dependencies
|
105
|
+
end
|
106
|
+
|
107
|
+
should_deactivate_and_reactivate_dependencies
|
108
|
+
end #with dependencies, @dependencies, that are dependent destroy, and with auto_configure_dependencies => true
|
109
|
+
|
110
|
+
context "with dependencies, @dependencies, that are :dependent => :delete_all , and with auto_configure_dependencies => true" do
|
111
|
+
setup do
|
112
|
+
@item.class.instance_eval { has_many :deactivatable_dependencies, :dependent => :delete_all }
|
113
|
+
@item.class.instance_eval { acts_as_deactivatable :auto_configure_dependencies => true }
|
114
|
+
create_item_dependencies
|
115
|
+
end
|
116
|
+
|
117
|
+
should_deactivate_and_reactivate_dependencies
|
118
|
+
end #with dependencies, @dependencies, that are dependent destroy, and with auto_configure_dependencies => true
|
119
|
+
|
120
|
+
context "with a single dependency" do
|
121
|
+
setup do
|
122
|
+
@item.class.instance_eval { has_one :deactivatable_dependency }
|
123
|
+
@item.class.instance_eval { acts_as_deactivatable :dependencies => [:deactivatable_dependency] }
|
124
|
+
@dependency = DeactivatableDependency.new
|
125
|
+
@item.deactivatable_dependency = @dependency
|
126
|
+
@item.save!
|
127
|
+
@dependencies = [@dependency]
|
128
|
+
end
|
129
|
+
|
130
|
+
should_deactivate_and_reactivate_dependencies
|
131
|
+
|
132
|
+
context "that is nil" do
|
133
|
+
setup do
|
134
|
+
@item.deactivatable_dependency = nil
|
135
|
+
@item.save!
|
136
|
+
end
|
137
|
+
|
138
|
+
|
139
|
+
should "not raise an exception when deactivated" do
|
140
|
+
assert_nothing_raised { @item.deactivate! }
|
141
|
+
end
|
142
|
+
end #that is nil
|
143
|
+
end #with a single dependency
|
144
|
+
|
92
145
|
end #An active item, @item
|
146
|
+
|
147
|
+
private
|
148
|
+
def create_item_dependencies
|
149
|
+
@dependencies = (0..5).map { DeactivatableDependency.new }
|
150
|
+
@item.deactivatable_dependencies = @dependencies
|
151
|
+
end
|
93
152
|
|
94
153
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: deactivatable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Greg Fitzgerald
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-11-
|
12
|
+
date: 2009-11-10 00:00:00 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|