acts_as_paranoid 0.5.0.beta2 → 0.5.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e64b4e62e3467e6208b4b06d4f6f6f45b5758888
4
- data.tar.gz: 1bf27545571d18596daa573546c84811da6fc5dd
3
+ metadata.gz: 124d271ce76db90e3e605685839c061359d22ff6
4
+ data.tar.gz: 18fd8e01afccccf40e31b722bad341434c2d1899
5
5
  SHA512:
6
- metadata.gz: 8b4cc3ccb8a881344891c1ded817044c805d3dada173b769725504679c7ab377ce2c078a2f950f093339a8ecd1892532d35777fc8f02231a0fdb8c39e33a5feb
7
- data.tar.gz: 15d82db6a8ec57720936cbba69dad58ceb98369d7b273610a7594e40d2ba77d08565603676670591e6c1e8c46ff01b02e6fc869215c0f68a8d5f84a0c0c0a689
6
+ metadata.gz: 113820d1b627fecfe8167342678b992b39af55758e82e2e5115e4ab9b69831d950fd605cc40cb2668178b37e83b6a0e80b68240a9fbee9b65982eeb365ab0c02
7
+ data.tar.gz: ddecec89fcc2e85ad58237bac886cc6bf072c28d5bf249cdc4714f3ab356275d0ceee470fafac867966c976452260f8022d53e10e5b750aa7d16fa8a38c9c2be
data/README.md CHANGED
@@ -8,9 +8,9 @@ This gem can be used to hide records instead of deleting them, making them recov
8
8
 
9
9
  ## Support
10
10
 
11
- **This branch targets Rails 4.x.**
11
+ **This branch targets Rails 4.x. and 5.x**
12
12
 
13
- If you're working with another version, switch to the corresponding branch, or require an older version of the acts_as_paranoid gem.
13
+ If you're working with another version, switch to the corresponding branch, or require an older version of the `acts_as_paranoid` gem.
14
14
 
15
15
  ## Usage
16
16
 
@@ -37,12 +37,18 @@ The values shown are the defaults. While *column* can be anything (as long as it
37
37
 
38
38
  If your column type is a `string`, you can also specify which value to use when marking an object as deleted by passing `:deleted_value` (default is "deleted"). Any records with a non-matching value in this column will be treated normally (ie: not deleted).
39
39
 
40
+ If your column type is a `boolean`, it is possible to specify `allow_nulls` option which is `true` by default. When set to `false`, entities that have `false` value in this column will be considered not deleted, and those which have `true` will be considered deleted. When `true` everything that has a not-null value will be considered deleted.
41
+
40
42
  ### Filtering
41
43
 
42
- If a record is deleted by ActsAsParanoid, it won't be retrieved when accessing the database. So, `Paranoiac.all` will **not** include the deleted_records. if you want to access them, you have 2 choices:
44
+ If a record is deleted by ActsAsParanoid, it won't be retrieved when accessing the database.
45
+
46
+ So, `Paranoiac.all` will **not** include the **deleted records**.
47
+
48
+ When you want to access them, you have 2 choices:
43
49
 
44
50
  ```ruby
45
- Paranoiac.only_deleted # retrieves the deleted records
51
+ Paranoiac.only_deleted # retrieves only the deleted records
46
52
  Paranoiac.with_deleted # retrieves all records, deleted or not
47
53
  ```
48
54
 
@@ -67,7 +73,13 @@ paranoiac.destroy!
67
73
  Paranoiac.delete_all!(conditions)
68
74
  ```
69
75
 
70
- You can also permanently delete a record by calling `destroy` or `delete_all` on it **twice**. If a record was already deleted (hidden by ActsAsParanoid) and you delete it again, it will be removed from the database. Take this example:
76
+ You can also permanently delete a record by calling `destroy_fully!` on the object.
77
+
78
+ Alternatively you can permanently delete a record by calling `destroy` or `delete_all` on the object **twice**.
79
+
80
+ If a record was already deleted (hidden by `ActsAsParanoid`) and you delete it again, it will be removed from the database.
81
+
82
+ Take this example:
71
83
 
72
84
  ```ruby
73
85
  p = Paranoiac.first
@@ -83,7 +95,9 @@ Recovery is easy. Just invoke `recover` on it, like this:
83
95
  Paranoiac.only_deleted.where("name = ?", "not dead yet").first.recover
84
96
  ```
85
97
 
86
- All associations marked as `:dependent => :destroy` are also recursively recovered. If you would like to disable this behavior, you can call `recover` with the `recursive` option:
98
+ All associations marked as `:dependent => :destroy` are also recursively recovered.
99
+
100
+ If you would like to disable this behavior, you can call `recover` with the `recursive` option:
87
101
 
88
102
  ```ruby
89
103
  Paranoiac.only_deleted.where("name = ?", "not dead yet").first.recover(:recursive => false)
@@ -97,7 +111,13 @@ class Paranoiac < ActiveRecord::Base
97
111
  end
98
112
  ```
99
113
 
100
- By default, dependent records will be recovered if they were deleted within 2 minutes of the object upon which they depend. This restores the objects to the state before the recursive deletion without restoring other objects that were deleted earlier. The behavior is only available when both parent and dependant are using timestamp fields to mark deletion, which is the default behavior. This window can be changed with the `dependent_recovery_window` option:
114
+ By default, dependent records will be recovered if they were deleted within 2 minutes of the object upon which they depend.
115
+
116
+ This restores the objects to the state before the recursive deletion without restoring other objects that were deleted earlier.
117
+
118
+ The behavior is only available when both parent and dependant are using timestamp fields to mark deletion, which is the default behavior.
119
+
120
+ This window can be changed with the `dependent_recovery_window` option:
101
121
 
102
122
  ```ruby
103
123
  class Paranoiac < ActiveRecord::Base
@@ -125,9 +145,9 @@ ActiveRecord's built-in uniqueness validation does not account for records delet
125
145
 
126
146
  ```ruby
127
147
  class Paranoiac < ActiveRecord::Base
128
- acts_as_paranoid
129
- validates_as_paranoid
130
- validates_uniqueness_of_without_deleted :name
148
+ acts_as_paranoid
149
+ validates_as_paranoid
150
+ validates_uniqueness_of_without_deleted :name
131
151
  end
132
152
 
133
153
  p1 = Paranoiac.create(:name => 'foo')
@@ -150,13 +170,15 @@ Paranoiac.with_deleted.first.deleted? #=> true
150
170
 
151
171
  ### Scopes
152
172
 
153
- As you've probably guessed, `with_deleted` and `only_deleted` are scopes. You can, however, chain them freely with other scopes you might have. This
173
+ As you've probably guessed, `with_deleted` and `only_deleted` are scopes. You can, however, chain them freely with other scopes you might have.
174
+
175
+ For example:
154
176
 
155
177
  ```ruby
156
178
  Paranoiac.pretty.with_deleted
157
179
  ```
158
180
 
159
- is exactly the same as
181
+ This is exactly the same as:
160
182
 
161
183
  ```ruby
162
184
  Paranoiac.with_deleted.pretty
@@ -166,8 +188,8 @@ You can work freely with scopes and it will just work:
166
188
 
167
189
  ```ruby
168
190
  class Paranoiac < ActiveRecord::Base
169
- acts_as_paranoid
170
- scope :pretty, where(:pretty => true)
191
+ acts_as_paranoid
192
+ scope :pretty, where(:pretty => true)
171
193
  end
172
194
 
173
195
  Paranoiac.create(:pretty => true)
@@ -185,7 +207,9 @@ Paranoiac.pretty.only_deleted.count #=> 1
185
207
 
186
208
  ### Associations
187
209
 
188
- Associations are also supported. From the simplest behaviors you'd expect to more nifty things like the ones mentioned previously or the usage of the `:with_deleted` option with `belongs_to`
210
+ Associations are also supported.
211
+
212
+ From the simplest behaviors you'd expect to more nifty things like the ones mentioned previously or the usage of the `:with_deleted` option with `belongs_to`
189
213
 
190
214
  ```ruby
191
215
  class Parent < ActiveRecord::Base
@@ -197,7 +221,7 @@ class ParanoiacChild < ActiveRecord::Base
197
221
  belongs_to :parent
198
222
 
199
223
  # You may need to provide a foreign_key like this
200
- belongs_to :parent_including_deleted, :class_name => "Parent", foreign_key => 'parent_id', :with_deleted => true
224
+ belongs_to :parent_including_deleted, :class_name => "Parent", :foreign_key => 'parent_id', :with_deleted => true
201
225
  end
202
226
 
203
227
  parent = Parent.first
@@ -231,5 +255,6 @@ Watch out for these caveats:
231
255
  * To [Gonçalo Silva](https://github.com/goncalossilva) for supporting this gem prior to v0.4.3
232
256
  * To [Jean Boussier](https://github.com/byroot) for initial Rails 4.0.0 support
233
257
  * To [Matijs van Zuijlen](https://github.com/mvz) for Rails 4.1 and 4.2 support
258
+ * To [Andrey Ponomarenko](https://github.com/sjke) for Rails 5 support
234
259
 
235
260
  See `LICENSE`.
@@ -2,6 +2,7 @@ require 'acts_as_paranoid/core'
2
2
  require 'acts_as_paranoid/associations'
3
3
  require 'acts_as_paranoid/validations'
4
4
  require 'acts_as_paranoid/relation'
5
+ require 'acts_as_paranoid/preloader_association'
5
6
 
6
7
  module ActsAsParanoid
7
8
 
@@ -20,6 +21,7 @@ module ActsAsParanoid
20
21
 
21
22
  self.paranoid_configuration = { :column => "deleted_at", :column_type => "time", :recover_dependent_associations => true, :dependent_recovery_window => 2.minutes }
22
23
  self.paranoid_configuration.merge!({ :deleted_value => "deleted" }) if options[:column_type] == "string"
24
+ self.paranoid_configuration.merge!({ :allow_nulls => true }) if options[:column_type] == "boolean"
23
25
  self.paranoid_configuration.merge!(options) # user options
24
26
 
25
27
  raise ArgumentError, "'time', 'boolean' or 'string' expected for :column_type option, got #{paranoid_configuration[:column_type]}" unless ['time', 'boolean', 'string'].include? paranoid_configuration[:column_type]
@@ -31,15 +33,15 @@ module ActsAsParanoid
31
33
  include ActsAsParanoid::Core
32
34
 
33
35
  # Magic!
34
- default_scope { where(paranoid_default_scope_sql) }
36
+ default_scope { where(paranoid_default_scope) }
35
37
 
36
38
  if paranoid_configuration[:column_type] == 'time'
37
39
  scope :deleted_inside_time_window, lambda {|time, window|
38
40
  deleted_after_time((time - window)).deleted_before_time((time + window))
39
41
  }
40
42
 
41
- scope :deleted_after_time, lambda { |time| where("#{paranoid_column} > ?", time) }
42
- scope :deleted_before_time, lambda { |time| where("#{paranoid_column} < ?", time) }
43
+ scope :deleted_after_time, lambda { |time| where("#{self.table_name}.#{paranoid_column} > ?", time) }
44
+ scope :deleted_before_time, lambda { |time| where("#{self.table_name}.#{paranoid_column} < ?", time) }
43
45
  end
44
46
  end
45
47
  end
@@ -55,3 +57,6 @@ ActiveRecord::Relation.send :include, ActsAsParanoid::Relation
55
57
 
56
58
  # Push the recover callback onto the activerecord callback list
57
59
  ActiveRecord::Callbacks::CALLBACKS.push(:before_recover, :after_recover)
60
+
61
+ # Use with_deleted in preloader build_scope
62
+ ActiveRecord::Associations::Preloader::Association.send :include, ActsAsParanoid::PreloaderAssociation
@@ -23,9 +23,11 @@ module ActsAsParanoid
23
23
 
24
24
  def only_deleted
25
25
  if string_type_with_deleted_value?
26
- without_paranoid_default_scope.where("#{paranoid_column_reference} IS ?", paranoid_configuration[:deleted_value])
26
+ without_paranoid_default_scope.where(paranoid_column_reference => paranoid_configuration[:deleted_value])
27
+ elsif boolean_type_not_nullable?
28
+ without_paranoid_default_scope.where(paranoid_column_reference => true)
27
29
  else
28
- without_paranoid_default_scope.where("#{paranoid_column_reference} IS NOT ?", nil)
30
+ without_paranoid_default_scope.where.not(paranoid_column_reference => nil)
29
31
  end
30
32
  end
31
33
 
@@ -37,13 +39,14 @@ module ActsAsParanoid
37
39
  where(conditions).update_all(["#{paranoid_configuration[:column]} = ?", delete_now_value])
38
40
  end
39
41
 
40
- def paranoid_default_scope_sql
42
+ def paranoid_default_scope
41
43
  if string_type_with_deleted_value?
42
44
  self.all.table[paranoid_column].eq(nil).
43
- or(self.all.table[paranoid_column].not_eq(paranoid_configuration[:deleted_value])).
44
- to_sql
45
+ or(self.all.table[paranoid_column].not_eq(paranoid_configuration[:deleted_value]))
46
+ elsif boolean_type_not_nullable?
47
+ self.all.table[paranoid_column].eq(false)
45
48
  else
46
- self.all.table[paranoid_column].eq(nil).to_sql
49
+ self.all.table[paranoid_column].eq(nil)
47
50
  end
48
51
  end
49
52
 
@@ -51,6 +54,10 @@ module ActsAsParanoid
51
54
  paranoid_column_type == :string && !paranoid_configuration[:deleted_value].nil?
52
55
  end
53
56
 
57
+ def boolean_type_not_nullable?
58
+ paranoid_column_type == :boolean && !paranoid_configuration[:allow_nulls]
59
+ end
60
+
54
61
  def paranoid_column
55
62
  paranoid_configuration[:column].to_sym
56
63
  end
@@ -75,12 +82,15 @@ module ActsAsParanoid
75
82
 
76
83
  def without_paranoid_default_scope
77
84
  scope = self.all
78
- if scope.where_values.include? paranoid_default_scope_sql
79
- # ActiveRecord 4.1
80
- scope.where_values.delete(paranoid_default_scope_sql)
85
+
86
+ if ActiveRecord::VERSION::MAJOR < 5
87
+ # ActiveRecord 4.0.*
88
+ scope = scope.with_default_scope if ActiveRecord::VERSION::MINOR < 1
89
+ scope.where_values.delete(paranoid_default_scope)
81
90
  else
82
- scope = scope.with_default_scope
83
- scope.where_values.delete(paranoid_default_scope_sql)
91
+ scope = scope.unscope(where: paranoid_default_scope)
92
+ # Fix problems with unscope group chain
93
+ scope = scope.unscoped if scope.to_sql.include? paranoid_default_scope.to_sql
84
94
  end
85
95
 
86
96
  scope
@@ -122,9 +132,7 @@ module ActsAsParanoid
122
132
  end
123
133
  end
124
134
 
125
- def destroy
126
- destroy!
127
- end
135
+ alias_method :destroy, :destroy!
128
136
 
129
137
  def recover(options={})
130
138
  options = {
@@ -179,8 +187,13 @@ module ActsAsParanoid
179
187
  end
180
188
 
181
189
  def deleted?
182
- !(paranoid_value.nil? ||
183
- (self.class.string_type_with_deleted_value? && paranoid_value != self.class.delete_now_value))
190
+ !if self.class.string_type_with_deleted_value?
191
+ paranoid_value != self.class.delete_now_value || paranoid_value.nil?
192
+ elsif self.class.boolean_type_not_nullable?
193
+ paranoid_value == false
194
+ else
195
+ paranoid_value.nil?
196
+ end
184
197
  end
185
198
 
186
199
  alias_method :destroyed?, :deleted?
@@ -0,0 +1,15 @@
1
+ module ActsAsParanoid
2
+ module PreloaderAssociation
3
+ def self.included(base)
4
+ base.class_eval do
5
+ def build_scope_with_deleted
6
+ scope = build_scope_without_deleted
7
+ scope = scope.with_deleted if options[:with_deleted] && klass.respond_to?(:with_deleted)
8
+ scope
9
+ end
10
+
11
+ alias_method_chain :build_scope, :deleted
12
+ end
13
+ end
14
+ end
15
+ end
@@ -6,42 +6,76 @@ module ActsAsParanoid
6
6
  base.extend ClassMethods
7
7
  end
8
8
 
9
- class UniquenessWithoutDeletedValidator < ActiveRecord::Validations::UniquenessValidator
10
- def validate_each(record, attribute, value)
11
- finder_class = find_finder_class_for(record)
12
- table = finder_class.arel_table
13
-
14
- # TODO: Use record.class.column_types[attribute.to_s].coder ?
15
- coder = record.class.column_types[attribute.to_s]
16
-
17
- if value && coder
18
- value = if coder.respond_to? :type_cast_for_database
19
- coder.type_cast_for_database value
20
- else
21
- coder.type_cast_for_write value
22
- end
9
+ class UniquenessWithoutDeletedValidator
10
+ def self.[](version)
11
+ version = version.to_s
12
+ name = "V#{version.tr('.', '_')}"
13
+ unless constants.include? name.to_sym
14
+ raise "Unknown validator version #{version.inspect}; expected one of #{constants.sort.join(', ')}"
23
15
  end
16
+ const_get name
17
+ end
18
+
19
+ class V5 < ActiveRecord::Validations::UniquenessValidator
20
+ def validate_each(record, attribute, value)
21
+ finder_class = find_finder_class_for(record)
22
+ table = finder_class.arel_table
23
+
24
+ coder = record.class.attribute_types[attribute.to_s]
25
+ value = coder.type_cast_for_schema value if value && coder
24
26
 
25
- relation = build_relation(finder_class, table, attribute, value)
26
- [Array(finder_class.primary_key), Array(record.send(:id))].transpose.each do |pk_key, pk_value|
27
- relation = relation.and(table[pk_key.to_sym].not_eq(pk_value))
28
- end if record.persisted?
27
+ relation = build_relation(finder_class, table, attribute, value)
28
+ [Array(finder_class.primary_key), Array(record.send(:id))].transpose.each do |pk_key, pk_value|
29
+ relation = relation.where(table[pk_key.to_sym].not_eq(pk_value))
30
+ end if record.persisted?
29
31
 
30
- Array.wrap(options[:scope]).each do |scope_item|
31
- scope_value = record.send(scope_item)
32
- relation = relation.and(table[scope_item].eq(scope_value))
32
+ Array.wrap(options[:scope]).each do |scope_item|
33
+ relation = relation.where(table[scope_item].eq(record.public_send(scope_item)))
34
+ end
35
+
36
+ if relation.where(finder_class.paranoid_default_scope).where(relation).exists?
37
+ record.errors.add(attribute, :taken, options.except(:case_sensitive, :scope).merge(:value => value))
38
+ end
33
39
  end
40
+ end
41
+
42
+ class V4 < ActiveRecord::Validations::UniquenessValidator
43
+ def validate_each(record, attribute, value)
44
+ finder_class = find_finder_class_for(record)
45
+ table = finder_class.arel_table
46
+
47
+ # TODO: Use record.class.column_types[attribute.to_s].coder ?
48
+ coder = record.class.column_types[attribute.to_s]
49
+
50
+ if value && coder
51
+ value = if coder.respond_to? :type_cast_for_database
52
+ coder.type_cast_for_database value
53
+ else
54
+ coder.type_cast_for_write value
55
+ end
56
+ end
57
+
58
+ relation = build_relation(finder_class, table, attribute, value)
59
+ [Array(finder_class.primary_key), Array(record.send(:id))].transpose.each do |pk_key, pk_value|
60
+ relation = relation.and(table[pk_key.to_sym].not_eq(pk_value))
61
+ end if record.persisted?
62
+
63
+ Array.wrap(options[:scope]).each do |scope_item|
64
+ scope_value = record.send(scope_item)
65
+ relation = relation.and(table[scope_item].eq(scope_value))
66
+ end
34
67
 
35
- # Re-add ActsAsParanoid default scope conditions manually.
36
- if finder_class.unscoped.where(finder_class.paranoid_default_scope_sql).where(relation).exists?
37
- record.errors.add(attribute, :taken, options.except(:case_sensitive, :scope).merge(:value => value))
68
+ # Re-add ActsAsParanoid default scope conditions manually.
69
+ if finder_class.unscoped.where(finder_class.paranoid_default_scope).where(relation).exists?
70
+ record.errors.add(attribute, :taken, options.except(:case_sensitive, :scope).merge(:value => value))
71
+ end
38
72
  end
39
73
  end
40
74
  end
41
75
 
42
76
  module ClassMethods
43
77
  def validates_uniqueness_of_without_deleted(*attr_names)
44
- validates_with UniquenessWithoutDeletedValidator, _merge_attributes(attr_names)
78
+ validates_with UniquenessWithoutDeletedValidator[ActiveRecord::VERSION::MAJOR], _merge_attributes(attr_names)
45
79
  end
46
80
  end
47
81
  end
@@ -1,3 +1,3 @@
1
1
  module ActsAsParanoid
2
- VERSION = "0.5.0.beta2"
2
+ VERSION = "0.5.0.rc1"
3
3
  end
@@ -304,8 +304,8 @@ class ParanoidTest < ParanoidBaseTest
304
304
  @paranoid_with_callback.recover
305
305
  end
306
306
 
307
- assert @paranoid_with_callback.called_before_recover
308
- assert @paranoid_with_callback.called_after_recover
307
+ assert @paranoid_with_callback.called_before_recover
308
+ assert @paranoid_with_callback.called_after_recover
309
309
  end
310
310
 
311
311
  def test_delete_by_multiple_id_is_paranoid
@@ -393,4 +393,44 @@ class ParanoidTest < ParanoidBaseTest
393
393
  2.times { ps.destroy }
394
394
  assert_equal 0, ParanoidString.with_deleted.where(:id => ps).count
395
395
  end
396
+
397
+ # Test boolean type columns, that are not nullable
398
+ def test_boolean_type_with_no_nil_value_before_destroy
399
+ ps = ParanoidBooleanNotNullable.create!()
400
+ assert_equal 1, ParanoidBooleanNotNullable.where(:id => ps).count
401
+ end
402
+
403
+ def test_boolean_type_with_no_nil_value_after_destroy
404
+ ps = ParanoidBooleanNotNullable.create!()
405
+ ps.destroy
406
+ assert_equal 0, ParanoidBooleanNotNullable.where(:id => ps).count
407
+ end
408
+
409
+ def test_boolean_type_with_no_nil_value_before_destroy_with_deleted
410
+ ps = ParanoidBooleanNotNullable.create!()
411
+ assert_equal 1, ParanoidBooleanNotNullable.with_deleted.where(:id => ps).count
412
+ end
413
+
414
+ def test_boolean_type_with_no_nil_value_after_destroy_with_deleted
415
+ ps = ParanoidBooleanNotNullable.create!()
416
+ ps.destroy
417
+ assert_equal 1, ParanoidBooleanNotNullable.with_deleted.where(:id => ps).count
418
+ end
419
+
420
+ def test_boolean_type_with_no_nil_value_before_destroy_only_deleted
421
+ ps = ParanoidBooleanNotNullable.create!()
422
+ assert_equal 0, ParanoidBooleanNotNullable.only_deleted.where(:id => ps).count
423
+ end
424
+
425
+ def test_boolean_type_with_no_nil_value_after_destroy_only_deleted
426
+ ps = ParanoidBooleanNotNullable.create!()
427
+ ps.destroy
428
+ assert_equal 1, ParanoidBooleanNotNullable.only_deleted.where(:id => ps).count
429
+ end
430
+
431
+ def test_boolean_type_with_no_nil_value_after_destroyed_twice
432
+ ps = ParanoidBooleanNotNullable.create!()
433
+ 2.times { ps.destroy }
434
+ assert_equal 0, ParanoidBooleanNotNullable.with_deleted.where(:id => ps).count
435
+ end
396
436
  end
@@ -111,14 +111,14 @@ def setup_db
111
111
 
112
112
  create_table :super_paranoids do |t|
113
113
  t.string :type
114
- t.references :has_many_inherited_super_paranoidz
114
+ t.references :has_many_inherited_super_paranoidz, index: { name: 'index__sp_id_on_has_many_isp' }
115
115
  t.datetime :deleted_at
116
116
 
117
117
  timestamps t
118
118
  end
119
119
 
120
120
  create_table :has_many_inherited_super_paranoidzs do |t|
121
- t.references :super_paranoidz
121
+ t.references :super_paranoidz, index: { name: 'index_has_many_isp_on_sp_id' }
122
122
  t.datetime :deleted_at
123
123
 
124
124
  timestamps t
@@ -181,6 +181,33 @@ def setup_db
181
181
  t.string :paranoid_thing_type
182
182
  t.datetime :deleted_at
183
183
  end
184
+
185
+ create_table :paranoid_boolean_not_nullables do |t|
186
+ t.string :name
187
+ t.boolean :deleted, :boolean, :null => false, :default => false
188
+ end
189
+
190
+ create_table :paranoid_belongs_to_polymorphics do |t|
191
+ t.string :name
192
+ t.string :parent_type
193
+ t.integer :parent_id
194
+ t.datetime :deleted_at
195
+
196
+ t.timestamps
197
+ end
198
+
199
+ create_table :not_paranoid_has_many_as_parents do |t|
200
+ t.string :name
201
+
202
+ t.timestamps
203
+ end
204
+
205
+ create_table :paranoid_has_many_as_parents do |t|
206
+ t.string :name
207
+ t.datetime :deleted_at
208
+
209
+ t.timestamps
210
+ end
184
211
  end
185
212
  end
186
213
 
@@ -190,9 +217,12 @@ def timestamps(table)
190
217
  end
191
218
 
192
219
  def teardown_db
193
- ActiveRecord::Base.connection.tables.each do |table|
194
- ActiveRecord::Base.connection.drop_table(table)
220
+ tables = if ActiveRecord::VERSION::MAJOR < 5
221
+ ActiveRecord::Base.connection.tables
222
+ else
223
+ ActiveRecord::Base.connection.data_sources
195
224
  end
225
+ tables.each { |table| ActiveRecord::Base.connection.drop_table(table) }
196
226
  end
197
227
 
198
228
  class ParanoidTime < ActiveRecord::Base
@@ -351,6 +381,20 @@ class ParanoidWithScopedValidation < ActiveRecord::Base
351
381
  validates_uniqueness_of :name, :scope => :category
352
382
  end
353
383
 
384
+ class ParanoidBelongsToPolymorphic < ActiveRecord::Base
385
+ acts_as_paranoid
386
+ belongs_to :parent, :polymorphic => true, :with_deleted => true
387
+ end
388
+
389
+ class NotParanoidHasManyAsParent < ActiveRecord::Base
390
+ has_many :paranoid_belongs_to_polymorphics, :as => :parent, :dependent => :destroy
391
+ end
392
+
393
+ class ParanoidHasManyAsParent < ActiveRecord::Base
394
+ acts_as_paranoid
395
+ has_many :paranoid_belongs_to_polymorphics, :as => :parent, :dependent => :destroy
396
+ end
397
+
354
398
  class ParanoidBaseTest < ActiveSupport::TestCase
355
399
  def setup
356
400
  setup_db
@@ -421,3 +465,8 @@ class ParanoidSection < ActiveRecord::Base
421
465
  belongs_to :paranoid_time
422
466
  belongs_to :paranoid_thing, :polymorphic => true, :dependent => :destroy
423
467
  end
468
+
469
+ class ParanoidBooleanNotNullable < ActiveRecord::Base
470
+ acts_as_paranoid column: 'deleted', column_type: 'boolean', allow_nulls: false
471
+ end
472
+
@@ -0,0 +1,27 @@
1
+ require 'test_helper'
2
+
3
+ class PreloaderAssociationTest < ParanoidBaseTest
4
+ def test_includes_with_deleted
5
+ paranoid_time = ParanoidTime.first
6
+ paranoid_has_many_dependant = paranoid_time.paranoid_has_many_dependants.create(:name => 'dependant!')
7
+
8
+ paranoid_time.destroy
9
+
10
+ ParanoidHasManyDependant.with_deleted.includes(:paranoid_time_with_deleted).each do |hasmany|
11
+ assert_not_nil hasmany.paranoid_time_with_deleted
12
+ end
13
+ end
14
+
15
+ def test_includes_with_deleted_with_polymorphic_parent
16
+ not_paranoid_parent = NotParanoidHasManyAsParent.create(name: 'not paranoid parent')
17
+ paranoid_parent = ParanoidHasManyAsParent.create(name: 'paranoid parent')
18
+ ParanoidBelongsToPolymorphic.create(:name => 'belongs_to', :parent => not_paranoid_parent)
19
+ ParanoidBelongsToPolymorphic.create(:name => 'belongs_to', :parent => paranoid_parent)
20
+
21
+ paranoid_parent.destroy
22
+
23
+ ParanoidBelongsToPolymorphic.with_deleted.includes(:parent).each do |hasmany|
24
+ assert_not_nil hasmany.parent
25
+ end
26
+ end
27
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acts_as_paranoid
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0.beta2
4
+ version: 0.5.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zachary Scott
@@ -10,36 +10,48 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2015-09-17 00:00:00.000000000 Z
13
+ date: 2016-07-09 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activerecord
17
17
  requirement: !ruby/object:Gem::Requirement
18
18
  requirements:
19
- - - "~>"
19
+ - - ">="
20
20
  - !ruby/object:Gem::Version
21
21
  version: '4.0'
22
+ - - "<"
23
+ - !ruby/object:Gem::Version
24
+ version: '5.1'
22
25
  type: :runtime
23
26
  prerelease: false
24
27
  version_requirements: !ruby/object:Gem::Requirement
25
28
  requirements:
26
- - - "~>"
29
+ - - ">="
27
30
  - !ruby/object:Gem::Version
28
31
  version: '4.0'
32
+ - - "<"
33
+ - !ruby/object:Gem::Version
34
+ version: '5.1'
29
35
  - !ruby/object:Gem::Dependency
30
36
  name: activesupport
31
37
  requirement: !ruby/object:Gem::Requirement
32
38
  requirements:
33
- - - "~>"
39
+ - - ">="
34
40
  - !ruby/object:Gem::Version
35
41
  version: '4.0'
42
+ - - "<"
43
+ - !ruby/object:Gem::Version
44
+ version: '5.1'
36
45
  type: :runtime
37
46
  prerelease: false
38
47
  version_requirements: !ruby/object:Gem::Requirement
39
48
  requirements:
40
- - - "~>"
49
+ - - ">="
41
50
  - !ruby/object:Gem::Version
42
51
  version: '4.0'
52
+ - - "<"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.1'
43
55
  - !ruby/object:Gem::Dependency
44
56
  name: bundler
45
57
  requirement: !ruby/object:Gem::Requirement
@@ -114,6 +126,7 @@ files:
114
126
  - lib/acts_as_paranoid.rb
115
127
  - lib/acts_as_paranoid/associations.rb
116
128
  - lib/acts_as_paranoid/core.rb
129
+ - lib/acts_as_paranoid/preloader_association.rb
117
130
  - lib/acts_as_paranoid/relation.rb
118
131
  - lib/acts_as_paranoid/validations.rb
119
132
  - lib/acts_as_paranoid/version.rb
@@ -122,6 +135,7 @@ files:
122
135
  - test/test_default_scopes.rb
123
136
  - test/test_helper.rb
124
137
  - test/test_inheritance.rb
138
+ - test/test_preloader_association.rb
125
139
  - test/test_relations.rb
126
140
  - test/test_validations.rb
127
141
  homepage: https://github.com/ActsAsParanoid/acts_as_paranoid
@@ -144,16 +158,18 @@ required_rubygems_version: !ruby/object:Gem::Requirement
144
158
  version: 1.3.6
145
159
  requirements: []
146
160
  rubyforge_project:
147
- rubygems_version: 2.4.5.1
161
+ rubygems_version: 2.5.1
148
162
  signing_key:
149
163
  specification_version: 4
150
164
  summary: Active Record plugin which allows you to hide and restore records without
151
165
  actually deleting them.
152
166
  test_files:
153
- - test/test_associations.rb
154
- - test/test_core.rb
155
- - test/test_default_scopes.rb
156
- - test/test_helper.rb
157
167
  - test/test_inheritance.rb
168
+ - test/test_preloader_association.rb
158
169
  - test/test_relations.rb
170
+ - test/test_core.rb
159
171
  - test/test_validations.rb
172
+ - test/test_associations.rb
173
+ - test/test_helper.rb
174
+ - test/test_default_scopes.rb
175
+ has_rdoc: