deleted_at 0.5.0 → 0.6.0.pre.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 29aee507393739895b695138545e5c6898c21d95
4
- data.tar.gz: f52a30d0f52ae37e24641f4e5a9c74324bc75186
2
+ SHA256:
3
+ metadata.gz: 5f702112df5aaab3c584dd6cf56a7f106aee39a41e1474d9e676ba0e960b72ab
4
+ data.tar.gz: 423ac85c6209fe354ead11a2b4b758ddebc5ec151251303cae885e4f72c69075
5
5
  SHA512:
6
- metadata.gz: 0b5c88eb056b584f4aebcbe24ebf28fd4e84d78dea0d23e39a23d107e48f2f28aac213c5880028bf38896bb395b6ba1e42341665846ec75dd25406afbf237883
7
- data.tar.gz: 128097c8e330be5ca187adb07b9f5ce8ef45a819400f9028b364c53a4af71d53bf34c6b7f128c6b9f804ae84c7e3176d8d9e0380f5a1d8e90f504d57b054e57a
6
+ metadata.gz: 260846b1749da3892ebc80a52b31d00a2a4f3738613bacfda250cd35582925c6795b76be40bdaafa5c5ac52b326e8da7a66af5ab64431ad26128d299735e1436
7
+ data.tar.gz: 49f6e710ac42079d03e88e993ebf2178c59a4faa189451255e962077c7dfbdaa23146e0028ca327edb0eafc8574296f56b06a27f00fc7e66bb22c397fd200d0f
data/CHANGELOG.md CHANGED
@@ -0,0 +1,57 @@
1
+ # DeletedAt
2
+
3
+ ## 0.6.0 _(September 4, 2018)_
4
+ - Added support for Rails 5.2
5
+ - Overhauled injection process for cleaner and more reliable sub-selecting
6
+
7
+ ## 0.5.0 _(June 25, 2018)_
8
+ - Removed use of invasive views in preference of sub-selects
9
+ - Dropped support for Ruby 2.0, 2.1, 2.2
10
+ - Dropped support for Rails 4.1
11
+ - Default `deleted_at` options using `Proc`
12
+
13
+ ## 0.4.0 _(Never Released)_
14
+ - Specs for Rails 4.0-5.1
15
+ - Uses `combustion` gem for cleaner and more comprehensive testing
16
+ - Added badges to ReadMe
17
+ - Using `:prepend` to leverage ancestry chain
18
+ - Add logger for internal use
19
+ - DRYd up init code
20
+ - Removed partially supported features
21
+ - Added DSL in migrations/schema for adding `deleted_at` timestamps to tables
22
+
23
+ ## 0.3.0 _(May 10, 2017)_
24
+ - Add specs
25
+ - Clean up dependencies
26
+ - Auto-init models after installing views
27
+ - Remove chained `create` methods
28
+
29
+ ## 0.2.6 _(April 06, 2017)_
30
+ - Add warning when no DB connection present
31
+
32
+ ## 0.2.5 _(March 28, 2017)_
33
+ - Extract injections to `.load` method
34
+
35
+ ## 0.2.4 _(February 03, 2017)_
36
+ - Use `becomes` to mask `::All` etc classes
37
+
38
+ ## 0.2.3 _(February 03, 2017)_
39
+ - Chain `create!` method to work properly
40
+
41
+ ## 0.2.2 _(February 03, 2017)_
42
+ - Chain `create` method to work properly
43
+
44
+ ## 0.2.1 _(February 03, 2017)_
45
+ - More reliable table name handling
46
+ - Changed API for installing views (e.g. `destroy_deleted_view`, `uninstall_deleted_view`)
47
+
48
+ ## 0.1.1 _(January 31, 2017)_
49
+ - Added instructions to readme
50
+ - Fixes stack-too-deep edge-case (by moving to `:include` over `:prepend`)
51
+
52
+ ## 0.1.0 _(January 30, 2017)_
53
+ - Renames primary table to `model_name/all`
54
+ - Creates views for each model using `deleted_at`
55
+ - `model_name/deleted`
56
+ - `model_name/present`
57
+ - Classes created to read from views (`::All`, `::Present`, `::Deleted`)
data/README.md CHANGED
@@ -1,12 +1,13 @@
1
- [![Version ](https://img.shields.io/gem/v/deleted_at.svg?maxAge=2592000)](https://rubygems.org/gems/deleted_at)
2
- [![Build Status ](https://travis-ci.org/TwilightCoders/deleted_at.svg)](https://travis-ci.org/TwilightCoders/deleted_at)
3
- [![Code Climate ](https://api.codeclimate.com/v1/badges/762cdcd63990efa768b0/maintainability)](https://codeclimate.com/github/TwilightCoders/deleted_at/maintainability)
4
- [![Test Coverage](https://codeclimate.com/github/TwilightCoders/deleted_at/badges/coverage.svg)](https://codeclimate.com/github/TwilightCoders/deleted_at/coverage)
5
- [![Dependencies ](https://badges.depfu.com/badges/5a2fe8068c0eaa5ad0e25a96373f1725/overview.svg)](https://depfu.com/github/TwilightCoders/deleted_at)
1
+ [![License ](https://img.shields.io/github/license/TwilightCoders/deleted_at.svg)]()
2
+ [![Version ](https://img.shields.io/gem/v/deleted_at.svg)](https://rubygems.org/gems/deleted_at)
3
+ [![Build Status](https://travis-ci.org/TwilightCoders/deleted_at.svg)](https://travis-ci.org/TwilightCoders/deleted_at)
4
+ [![Maintenence ](https://api.codeclimate.com/v1/badges/762cdcd63990efa768b0/maintainability)](https://codeclimate.com/github/TwilightCoders/deleted_at/maintainability)
5
+ [![Coverage ](https://codeclimate.com/github/TwilightCoders/deleted_at/badges/coverage.svg)](https://codeclimate.com/github/TwilightCoders/deleted_at/coverage)
6
+ [![Dependencies](https://img.shields.io/librariesio/github/twilightcoders/deleted_at.svg)](https://depfu.com/github/TwilightCoders/deleted_at)
6
7
 
7
8
  # DeletedAt
8
9
 
9
- Hide your "deleted" data (unless specifically asked for) without resorting to `default_scope` by leveraging in-line sub-selects. (See the [Upgrading](#upgrading) section)
10
+ Hide your "deleted" data (unless specifically asked for) [without resorting to](https://stackoverflow.com/a/25087337/1454158) `default_scope` by leveraging in-line sub-selects. (See the [Upgrading](#upgrading) section)
10
11
 
11
12
  ## Requirements
12
13
 
@@ -46,14 +47,10 @@ To work properly, the tables that back these models must have a `deleted_at` tim
46
47
  ```ruby
47
48
  class AddDeletedAtColumnToUsers < ActiveRecord::Migration
48
49
 
49
- def up
50
+ def change
50
51
  add_column :users, :deleted_at, 'timestamp with time zone'
51
52
  end
52
53
 
53
- def down
54
- remove_column :users, :deleted_at, 'timestamp with time zone'
55
- end
56
-
57
54
  end
58
55
  ```
59
56
 
@@ -62,7 +59,7 @@ If you're starting with a brand-new table, the existing `timestamps` DSL has bee
62
59
  ```ruby
63
60
  class CreatCommentsTable < ActiveRecord::Migration
64
61
 
65
- def up
62
+ def change
66
63
  create_table :comments do |t|
67
64
  # ...
68
65
  # to the `timestamps` DSL
@@ -70,19 +67,48 @@ class CreatCommentsTable < ActiveRecord::Migration
70
67
  end
71
68
  end
72
69
 
73
- def down
74
- drop_table :comments
70
+ end
71
+ ```
72
+
73
+ ## Performance
74
+
75
+ It's recommended (if your database engine supports it) to add partial indexes to the `deleted_at` columns. Remember that indexes work best when they represent a minority of the rows. It's up to you to determine the best index for your table.
76
+
77
+ Example 1:
78
+
79
+ You have a thriving business and your customers love your product and _rarely_ delete their account. You're likely to have way fewer rows `WHERE deleted_at IS NOT NULL`.
80
+
81
+ ```ruby
82
+ class IndexDeletedAtColumns < ActiveRecord::Migration
83
+
84
+ def change
85
+ add_index :users, :deleted_at, where: "deleted_at IS NOT NULL"
75
86
  end
76
87
 
77
88
  end
78
89
  ```
79
90
 
91
+ Example 2:
92
+
93
+ You use expiring OAuth2 tokens as part of your application's authentication process. As time grows without bound rows `WHERE deleted_at IS NULL` will pale in comparison.
94
+
95
+ ```ruby
96
+ class IndexDeletedAtColumns < ActiveRecord::Migration
97
+
98
+ def change
99
+ add_index :oauth_tokens, :deleted_at, where: "deleted_at IS NULL"
100
+ end
101
+
102
+ end
103
+ ```
104
+
105
+
80
106
  ## [Upgrading](#upgrading)
81
107
 
82
108
  If you've used `deleted_at` prior to v0.5.0, you'll need to migrate your schema. The new version of `deleted_at` no longer uses views, instead constructing a subselect on the relations. This significantly reduces code polution and monkey patching, as well as reducing the runtime memory usage for rails. Your Database will look (and be) a lot cleaner with no `deleted_at` views and your ERDs will be much cleaner as well.
83
109
 
84
110
  Here is an example of a migration for upgrading
85
- ```
111
+ ```ruby
86
112
  require 'deleted_at/legacy'
87
113
 
88
114
  DeletedAt.disable
data/lib/deleted_at.rb CHANGED
@@ -41,10 +41,10 @@ module DeletedAt
41
41
  end
42
42
 
43
43
  def self.install(model)
44
- logger.warn <<-STR
45
- Great news! You're using the new and improved version of DeletedAt. No more table renaming.
46
- You'll want to migrate your old models to use the new (non-view based) functionality.
47
- Follow the instructions at #{gemspec.homepage}.
44
+ logger.warn <<~STR
45
+ Great news! You're using the new and improved version of DeletedAt. No more table renaming.
46
+ You'll want to migrate your old models to use the new (non-view based) functionality.
47
+ Follow the instructions at #{gemspec.homepage}.
48
48
  STR
49
49
  end
50
50
 
@@ -5,31 +5,49 @@ module DeletedAt
5
5
  module ActiveRecord
6
6
 
7
7
  def self.prepended(subclass)
8
- subclass.const_get(:ActiveRecord_Relation).prepend(DeletedAt::Relation)
9
- subclass.const_get(:ActiveRecord_AssociationRelation).prepend(DeletedAt::Relation)
8
+ subclass.init_deleted_at_relations
10
9
  subclass.extend(ClassMethods)
11
10
  end
12
11
 
12
+ def initialize(*args)
13
+ super
14
+ @destroyed = !deleted_at.nil?
15
+ end
16
+
17
+ def destroy
18
+ soft_delete
19
+ super
20
+ end
21
+
22
+ def delete
23
+ soft_delete
24
+ super
25
+ end
26
+
27
+ private
28
+
29
+ def soft_delete
30
+ update_columns(self.class.deleted_at_attributes)
31
+ @destroyed = true
32
+ end
33
+
13
34
  module ClassMethods
14
35
 
15
36
  def inherited(subclass)
16
37
  super
17
- subclass.with_deleted_at self.deleted_at
18
- end
19
-
20
- def all
21
- const_get(:Present)
38
+ subclass.init_deleted_at_relations
22
39
  end
23
40
 
24
41
  def const_missing(const)
25
42
  case const
26
- when :All, :Deleted, :Present
27
- all_without_deleted_at.tap do |rel|
28
- rel.deleted_at_scope = const
43
+ when :All, :Deleted
44
+ all.tap do |_query|
45
+ _query.deleted_at_scope = const
29
46
  end
30
47
  else super
31
48
  end
32
49
  end
50
+
33
51
  end
34
52
 
35
53
  end
@@ -8,7 +8,6 @@ module DeletedAt
8
8
  class << subclass
9
9
  cattr_accessor :deleted_at
10
10
  self.deleted_at = {}
11
- alias all_without_deleted_at all
12
11
  end
13
12
 
14
13
  subclass.extend(ClassMethods)
@@ -43,6 +42,12 @@ module DeletedAt
43
42
  }
44
43
  end
45
44
 
45
+ def init_deleted_at_relations
46
+ instance_variable_get(:@relation_delegate_cache).each do |base, klass|
47
+ klass.send(:prepend, DeletedAt::Relation)
48
+ end
49
+ end
50
+
46
51
  end # End ClassMethods
47
52
 
48
53
  end
@@ -1,5 +1,4 @@
1
1
  module DeletedAt
2
-
3
2
  module Relation
4
3
 
5
4
  def self.prepended(subclass)
@@ -15,58 +14,45 @@ module DeletedAt
15
14
  def deleted_at_select
16
15
  scoped_arel = case deleted_at_scope
17
16
  when :Deleted
18
- table.where(table[deleted_at[:column]].not_eq(nil))
17
+ vanilla.dup.where(table[klass.deleted_at[:column]].not_eq(nil))
19
18
  when :Present
20
- table.where(table[deleted_at[:column]].eq(nil))
19
+ vanilla.dup.where(table[klass.deleted_at[:column]].eq(nil))
21
20
  end
22
21
  end
23
22
 
23
+ def vanilla
24
+ # @vanilla ||= klass.const_get(:All).unscope(:where).freeze
25
+ @vanilla ||= klass.unscoped.tap do |rel|
26
+ rel.deleted_at_scope = :All
27
+ end.freeze
28
+ end
24
29
 
25
- def deleted_at_subselect(arel)
30
+ # Rails 4.x
31
+ def from_value
26
32
  if (subselect = deleted_at_select)
27
- subselect.project(arel_columns(columns.map(&:name)))
28
- Arel::Nodes::TableAlias.new(Arel::Nodes::Grouping.new(subselect.ast), table_name)
33
+ [subselect, table_name]
34
+ else
35
+ super
29
36
  end
30
37
  end
31
38
 
32
- def build_arel
33
- super.tap do |arel|
34
- if (subselect = deleted_at_subselect(arel)) && !arel.froms.include?(subselect)
35
- DeletedAt.logger.debug("DeletedAt sub-selecting from #{subselect.to_sql}")
36
- arel.from(subselect)
37
- end
39
+ # Rails 5.x
40
+ def from_clause
41
+ if (subselect = deleted_at_select)
42
+ ::ActiveRecord::Relation::FromClause.new(subselect, table_name)
43
+ else
44
+ super
38
45
  end
39
46
  end
40
47
 
41
- # Deletes the records matching +conditions+ without instantiating the records
42
- # first, and hence not calling the +destroy+ method nor invoking callbacks. This
43
- # is a single SQL DELETE statement that goes straight to the database, much more
44
- # efficient than +destroy_all+. Be careful with relations though, in particular
45
- # <tt>:dependent</tt> rules defined on associations are not honored. Returns the
46
- # number of rows affected.
47
- #
48
- # Post.delete_all("person_id = 5 AND (category = 'Something' OR category = 'Else')")
49
- # Post.delete_all(["person_id = ? AND (category = ? OR category = ?)", 5, 'Something', 'Else'])
50
- # Post.where(person_id: 5).where(category: ['Something', 'Else']).delete_all
51
- #
52
- # Both calls delete the affected posts all at once with a single DELETE statement.
53
- # If you need to destroy dependent associations or call your <tt>before_*</tt> or
54
- # +after_destroy+ callbacks, use the +destroy_all+ method instead.
55
- #
56
- # If an invalid method is supplied, +delete_all+ raises an ActiveRecord error:
57
- #
58
- # Post.limit(100).delete_all
59
- # # => ActiveRecord::ActiveRecordError: delete_all doesn't support limit
60
48
  def delete_all(*args)
61
- conditions = args.pop
62
- if conditions
63
- ActiveSupport::Deprecation.warn(<<-MESSAGE.squish)
49
+ if args.pop
50
+ ActiveSupport::Deprecation.warn(<<~STR)
64
51
  Passing conditions to delete_all is not supported in DeletedAt
65
52
  To achieve the same use where(conditions).delete_all.
66
- MESSAGE
53
+ STR
67
54
  end
68
55
  update_all(klass.deleted_at_attributes)
69
56
  end
70
57
  end
71
-
72
58
  end
@@ -1,3 +1,3 @@
1
1
  module DeletedAt
2
- VERSION = "0.5.0"
2
+ VERSION = "0.6.0-1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: deleted_at
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0.pre.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dale Stevens
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-06-25 00:00:00.000000000 Z
11
+ date: 2018-09-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -16,7 +16,7 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '4.1'
19
+ version: '4.2'
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
22
  version: '6'
@@ -26,7 +26,7 @@ dependencies:
26
26
  requirements:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
- version: '4.1'
29
+ version: '4.2'
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
32
  version: '6'
@@ -136,12 +136,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
136
136
  version: '2.3'
137
137
  required_rubygems_version: !ruby/object:Gem::Requirement
138
138
  requirements:
139
- - - ">="
139
+ - - ">"
140
140
  - !ruby/object:Gem::Version
141
- version: '0'
141
+ version: 1.3.1
142
142
  requirements: []
143
143
  rubyforge_project:
144
- rubygems_version: 2.5.2.1
144
+ rubygems_version: 2.7.6
145
145
  signing_key:
146
146
  specification_version: 4
147
147
  summary: Soft delete your data, but keep it clean.