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 CHANGED
@@ -3,3 +3,4 @@
3
3
  coverage
4
4
  rdoc
5
5
  pkg
6
+ .project
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
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
- # *:dependencies* => A list of symbols specifying any associations that are also deactivatable. (This associations must separately be defined with acts_as_deactivatable).
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
- dependency.respond_to?(:map) ? dependency.map(&method) : dependency.__send__(method)
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
 
@@ -1,7 +1,6 @@
1
1
  class DeactivatableItem < ActiveRecord::Base
2
2
 
3
- has_many :deactivatable_dependencies
4
-
5
- acts_as_deactivatable :dependencies => [:deactivatable_dependencies]
3
+ acts_as_deactivatable
4
+
6
5
 
7
6
  end
@@ -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
- @dependencies = (0..5).map { DeactivatableDependency.new }
61
- @item.deactivatable_dependencies = @dependencies
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
- context "on a call to deactivate!" do
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.1
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-06 00:00:00 -05:00
12
+ date: 2009-11-10 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency