deleted_at 0.3.0 → 0.4.0rc1

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: 8a972a99558a55757fd3a8246f87b5ac0bc94308
4
- data.tar.gz: 82771e5aea1cb90ec9d97bc1c7855c17f34d755e
2
+ SHA256:
3
+ metadata.gz: c164168eb496804835ab5f48676d72a12fb549dccb649b0249355403db9b5b7e
4
+ data.tar.gz: 6e684b4ef6a4146f40b6a0684b5aa18df975894df8da62ec62907d34bece3ec9
5
5
  SHA512:
6
- metadata.gz: 929ab80f479d1a37400d45232c357474038e2ffb0d55599c761ecee6f327104695bd00ae47bd93ddb41c41104d99a5de5384069900a57b8c7e7b311b60047f22
7
- data.tar.gz: f7f73d1d179a03e468cd458bf3404b7e1c2b1116ac9e12ed4183725035d00696d0739457bee0fb865072b5cc18c5a3e7439928e016892b697612def031a31598
6
+ metadata.gz: f16daa013ef9ba2c06a42dea4ed2cd1d3e4008d419daa987aa01224408c1a11dd2d38ad93c5685119acfc28b46db4de240ff66ab93a629a7feec2dc632ddf905
7
+ data.tar.gz: 916c6f5c3e8cf4ebabcb628b23e4015fb16f3c83eb57ef5c393bdfafdb16973149dbedafcf3cfba593bd68f7da6f6dd39200c527ce3c9555fec88d303081bcd2
data/.gitignore CHANGED
@@ -1,16 +1,78 @@
1
- /.bundle/
2
- /.yardoc
3
- /Gemfile.lock
4
- /_yardoc/
5
- /coverage/
6
- /doc/
7
- /pkg/
8
- /spec/reports/
9
- /tmp/
10
- *.bundle
11
- *.so
1
+ # See http://help.github.com/ignore-files/ for more about ignoring files.
2
+ #
3
+ # If you find yourself ignoring temporary files generated by your text editor
4
+ # or operating system, you probably want to add a global ignore instead:
5
+ # git config --global core.excludesfile ~/.gitignore_global
6
+
7
+ # Database config and secrets
8
+ /config/database.yml
9
+ /config/secrets.yml
10
+
11
+ # Ignore bundler config
12
+ /.bundle
13
+
14
+ # Ignore client credentials
15
+ /config/client_api_credentials.yml
16
+
17
+ # Ignore the default SQLite database.
18
+ /db/*.sqlite3
19
+
20
+ # Ignore all logfiles and tempfiles.
21
+ /log/*.log
22
+ /tmp
23
+ /db/structure.sql
24
+ /doc/app/*
25
+ /vendor/cldr/*
26
+ /public/uploads/*
27
+ /public/photo/*
28
+ /public/test/*
29
+ /test/assets/*
30
+ /spec/assets/*
31
+ /public/assets/**
32
+ .powenv
33
+ .rvmrc
34
+ .env
35
+ .ruby-version
36
+
37
+ # Compiled source #
38
+ ###################
39
+ /build/
40
+ *.com
41
+ *.class
42
+ *.dll
43
+ *.exe
12
44
  *.o
13
- *.a
14
- *.DS_Store
15
- .editorconfig
16
- mkmf.log
45
+ *.so
46
+
47
+ # Packages #
48
+ ############
49
+ # it's better to unpack these files and commit the raw source
50
+ # git has its own built in compression methods
51
+ *.7z
52
+ *.dmg
53
+ *.gz
54
+ *.iso
55
+ *.jar
56
+ *.rar
57
+ *.tar
58
+ *.zip
59
+
60
+ # Logs and databases #
61
+ ######################
62
+ *.log
63
+ *.sql
64
+ *.sqlite
65
+
66
+ # OS generated files #
67
+ ######################
68
+ .DS_Store
69
+ .DS_Store?
70
+ ._*
71
+ .Spotlight-V100
72
+ .Trashes
73
+ Icon?
74
+ ehthumbs.db
75
+ Thumbs.db
76
+ /Gemfile.lock
77
+ /coverage
78
+ /.editorconfig
@@ -1,19 +1,43 @@
1
1
  language: ruby
2
2
  sudo: false
3
- rvm:
4
- - 2.0
5
- - 2.1
6
- - 2.2
7
- - 2.3.1
8
- - 2.4.0
3
+
9
4
  cache: bundler
10
5
  script:
11
6
  - bundle exec rspec
12
- services:
13
- - postgresql
7
+
8
+ after_success:
9
+ - bundle exec codeclimate-test-reporter
10
+
14
11
  addons:
15
- postgresql: "9.1"
12
+ postgresql: "9.3"
13
+
14
+ rvm:
15
+ - 2.4
16
+ - 2.3
17
+ - 2.2
18
+ - 2.1
19
+ - 2.0
20
+
21
+ gemfile:
22
+ - gemfiles/activerecord-5.1.Gemfile
23
+ - gemfiles/activerecord-5.0.Gemfile
24
+ - gemfiles/activerecord-4.2.Gemfile
25
+ - gemfiles/activerecord-4.1.Gemfile
26
+ - gemfiles/activerecord-4.0.Gemfile
27
+
28
+ matrix:
29
+ exclude:
30
+ - rvm: 2.0
31
+ gemfile: gemfiles/activerecord-5.0.Gemfile
32
+ - rvm: 2.0
33
+ gemfile: gemfiles/activerecord-5.1.Gemfile
34
+
35
+ - rvm: 2.1
36
+ gemfile: gemfiles/activerecord-5.0.Gemfile
37
+ - rvm: 2.1
38
+ gemfile: gemfiles/activerecord-5.1.Gemfile
16
39
 
17
- env:
18
- - RSPEC_VERSION="<2.99"
19
- - RSPEC_VERSION="~>3.0
40
+ - rvm: 2.4
41
+ gemfile: gemfiles/activerecord-4.0.Gemfile
42
+ - rvm: 2.4
43
+ gemfile: gemfiles/activerecord-4.1.Gemfile
data/Gemfile CHANGED
@@ -1,4 +1,19 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- # Specify your gem's dependencies in deleted_at.gemspec
4
3
  gemspec
4
+
5
+ group :test do
6
+
7
+ # Generates coverage stats of specs
8
+ gem 'simplecov'
9
+
10
+ # Publishes coverage to codeclimate
11
+ gem 'codeclimate-test-reporter'
12
+
13
+ gem 'rspec'
14
+
15
+ gem 'database_cleaner'
16
+
17
+ gem 'combustion'
18
+
19
+ end
data/README.md CHANGED
@@ -1,4 +1,9 @@
1
- # DeletedAt [![Build Status](https://travis-ci.org/TwilightCoders/deleted_at.svg?branch=master)](https://travis-ci.org/TwilightCoders/deleted_at) [![Code Climate](https://codeclimate.com/github/TwilightCoders/deleted_at/badges/gpa.svg)](https://codeclimate.com/github/TwilightCoders/deleted_at) [![Test Coverage](https://codeclimate.com/github/TwilightCoders/deleted_at/badges/coverage.svg)](https://codeclimate.com/github/TwilightCoders/deleted_at/coverage)
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)
4
+ [![Test Coverage](https://codeclimate.com/github/TwilightCoders/deleted_at/badges/coverage.svg)](https://codeclimate.com/github/TwilightCoders/deleted_at/coverage)
5
+
6
+ # DeletedAt
2
7
 
3
8
  Deleting data is never good. A common solution is to use `default_scope`, but conventional wisdom (and for good reason) deams this a bad practice. So how do we achieve the same effect with minimal intervention. What we're looking for is the cliche "clean" solution.
4
9
 
data/Rakefile CHANGED
@@ -1,6 +1,6 @@
1
1
  require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
2
+ require 'rspec/core/rake_task'
3
3
 
4
- RSpec::Core::RakeTask.new(:spec)
4
+ RSpec::Core::RakeTask.new
5
5
 
6
- task :default => :spec
6
+ task default: :spec
@@ -22,24 +22,21 @@ Gem::Specification.new do |spec|
22
22
  raise 'RubyGems 2.0 or newer is required to protect against public gem pushes.'
23
23
  end
24
24
 
25
- spec.files = `git ls-files -z`.split("\x0").reject do |f|
26
- f.match(%r{^(test|spec|features)/})
27
- end
28
-
29
- spec.bindir = "exe"
30
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
31
- spec.require_paths = ["lib"]
25
+ spec.files = `git ls-files -z`.split("\x0")
26
+ spec.bindir = 'bin'
27
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
28
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
29
+ spec.require_paths = ['lib', 'spec']
32
30
 
33
- rails_versions = ['>= 4.1', '< 5']
34
- spec.required_ruby_version = '>= 2.0.0'
31
+ rails_versions = ['>= 4', '< 6']
32
+ spec.required_ruby_version = '>= 2.0'
35
33
 
36
34
  spec.add_runtime_dependency 'pg', '~> 0'
37
- spec.add_runtime_dependency "activerecord", rails_versions
38
-
39
- spec.add_development_dependency "bundler", "~> 1.3"
40
- spec.add_development_dependency "rake", "~> 10.0"
41
- spec.add_development_dependency "rspec", "~> 3.0"
42
- spec.add_development_dependency "pry", "~> 0.10"
43
- spec.add_development_dependency "simplecov", ['>= 0.9.0', '<1.0.0']
44
- spec.add_development_dependency "codeclimate-test-reporter", "~> 1.0"
35
+ spec.add_runtime_dependency 'activerecord', rails_versions
36
+
37
+ spec.add_development_dependency 'pry-byebug', '~> 3'
38
+ spec.add_development_dependency 'bundler', '~> 1.3'
39
+ spec.add_development_dependency 'rake', '~> 10.0'
40
+ spec.add_development_dependency 'combustion', '~> 0.7'
41
+
45
42
  end
@@ -0,0 +1,3 @@
1
+ eval_gemfile File.join(File.dirname(__FILE__), "../Gemfile")
2
+
3
+ gem 'activerecord', '~> 4.0.0'
@@ -0,0 +1,3 @@
1
+ eval_gemfile File.join(File.dirname(__FILE__), "../Gemfile")
2
+
3
+ gem 'activerecord', '~> 4.1.0'
@@ -0,0 +1,3 @@
1
+ eval_gemfile File.join(File.dirname(__FILE__), "../Gemfile")
2
+
3
+ gem 'activerecord', '~> 4.2.0'
@@ -0,0 +1,3 @@
1
+ eval_gemfile File.join(File.dirname(__FILE__), "../Gemfile")
2
+
3
+ gem 'activerecord', '~> 5.0.0'
@@ -0,0 +1,3 @@
1
+ eval_gemfile File.join(File.dirname(__FILE__), "../Gemfile")
2
+
3
+ gem 'activerecord', '~> 5.1.0'
@@ -2,17 +2,32 @@ require "deleted_at/version"
2
2
  require 'deleted_at/views'
3
3
  require 'deleted_at/active_record/base'
4
4
  require 'deleted_at/active_record/relation'
5
+ require 'deleted_at/active_record/connection_adapters/abstract/schema_definition'
5
6
 
6
7
  require 'deleted_at/railtie' if defined?(Rails::Railtie)
7
8
 
8
9
  module DeletedAt
9
10
 
11
+ class << self
12
+ attr_writer :logger
13
+
14
+ def logger
15
+ @logger ||= Logger.new($stdout).tap do |log|
16
+ log.progname = self.name
17
+ log.level = Logger::INFO
18
+ end
19
+ end
20
+ end
21
+
10
22
  def self.load
11
- ::ActiveRecord::Relation.send :include, DeletedAt::ActiveRecord::Relation
23
+ ::ActiveRecord::Relation.send :prepend, DeletedAt::ActiveRecord::Relation
12
24
  ::ActiveRecord::Base.send :include, DeletedAt::ActiveRecord::Base
25
+ ::ActiveRecord::ConnectionAdapters::TableDefinition.send :prepend, DeletedAt::ActiveRecord::ConnectionAdapters::TableDefinition
13
26
  end
14
27
 
15
28
  def self.install(model)
29
+ return false unless model.has_deleted_at_column?
30
+
16
31
  DeletedAt::Views.install_present_view(model)
17
32
  DeletedAt::Views.install_deleted_view(model)
18
33
 
@@ -22,11 +37,17 @@ module DeletedAt
22
37
  end
23
38
 
24
39
  def self.uninstall(model)
40
+ return false unless model.has_deleted_at_column?
41
+
25
42
  DeletedAt::Views.uninstall_deleted_view(model)
26
43
  DeletedAt::Views.uninstall_present_view(model)
27
44
 
28
45
  # We've removed the database views, now remove the class extensions
29
- model.remove_class_views
46
+ DeletedAt::ActiveRecord::Base.remove_class_views(model)
47
+ end
48
+
49
+ def self.testify(value)
50
+ value == true || value == 't' || value == 1 || value == '1'
30
51
  end
31
52
 
32
53
  private
@@ -7,125 +7,61 @@ module DeletedAt
7
7
  extend ActiveSupport::Concern
8
8
 
9
9
  included do
10
- class_attribute :deleted_at_column, :original_table_name,
11
- :deleted_by_column, :deleted_by_class, :deleted_by_primary_key
12
-
13
- class << self
14
- [:archive_with_deleted_at?, :archive_with_deleted_by?].each do |sym|
15
- define_method(sym) do
16
- false
17
- end
18
- end
19
- end
10
+ class_attribute :archive_with_deleted_at
11
+ class_attribute :deleted_at_column
20
12
 
13
+ self.archive_with_deleted_at = false
21
14
  end
22
15
 
23
16
  module ClassMethods
24
17
 
25
18
  def with_deleted_at(options={})
26
19
 
27
- return warn("No DB connection found; skipping deleted_at initialization") unless ::ActiveRecord::Base.connected?
20
+ DeletedAt::ActiveRecord::Base.parse_options(self, options)
28
21
 
29
- parse_options(options)
30
-
31
- unless ::DeletedAt::Views.all_table_exists?(self) && ::DeletedAt::Views.deleted_view_exists?(self)
32
- return warn("You're trying to use `with_deleted_at` on #{name} but you have not installed the views, yet.")
33
- end
34
-
35
- unless columns.map(&:name).include?(deleted_at_column)
36
- return warn("Missing `#{deleted_at_column}` in `#{name}` when trying to employ `deleted_at`")
37
- end
38
-
39
- [:archive_with_deleted_at?, :archive_with_deleted_by?].each do |sym|
40
- class_eval <<-BBB
41
- def self.#{sym}
42
- true
43
- end
44
- BBB
45
- end
22
+ return DeletedAt.logger.warn("You're trying to use `with_deleted_at` on #{name} but you have not installed the views, yet.") unless
23
+ has_deleted_at_views?
46
24
 
25
+ return DeletedAt.logger.warn("Missing `#{deleted_at_column}` in `#{name}` when trying to employ `deleted_at`") unless
26
+ has_deleted_at_column?
47
27
 
48
28
  # We are confident at this point that the tables and views have been setup.
49
29
  # We need to do a bit of wizardy by setting the table name to the actual table
50
30
  # (at this point: model/all), such that the model has all the information
51
- # regarding its structure and intended behavior. Calling primary_key loads the
52
- # table data into the class.
53
- self.original_table_name = self.table_name
54
- self.table_name = ::DeletedAt::Views.all_table(self)
55
- primary_key = self.primary_key
56
- self.table_name = self.original_table_name
57
-
58
- setup_class_views
59
- with_deleted_by
60
- end
31
+ # regarding its structure and intended behavior. (e.g. setting primary key)
32
+ DeletedAt::Views.while_spoofing_table_name(self, ::DeletedAt::Views.all_table(self)) do
33
+ reset_primary_key
34
+ end
61
35
 
62
- def remove_class_views
63
- self.send(:remove_const, :All) if self.const_defined?(:All)
64
- self.send(:remove_const, :Deleted) if self.const_defined?(:Deleted)
36
+ DeletedAt::ActiveRecord::Base.setup_class_views(self)
65
37
  end
66
38
 
67
- private
68
39
 
69
- def parse_options(options)
70
- self.deleted_at_column = (options.try(:[], :deleted_at).try(:[], :column) || :deleted_at).to_s
71
- self.deleted_by_column = (options.try(:[], :deleted_by).try(:[], :column) || :deleted_by).to_s
72
- self.deleted_by_class = (options.try(:[], :deleted_by).try(:[], :class) || User)
73
- self.deleted_by_primary_key = (options.try(:[], :deleted_by).try(:[], :primary_key) || deleted_by_class.try(:primary_key)).to_s
74
- end
75
40
 
76
- def deleted_by_class_is_delete_at(klass)
77
- klass && (klass.archive_with_deleted_at? || self == klass)
41
+ def has_deleted_at_column?
42
+ columns.map(&:name).include?(deleted_at_column)
78
43
  end
79
44
 
80
- def with_deleted_by
81
- return unless (deleted_by_column && columns.map(&:name).include?(deleted_by_column) && deleted_by_class < ActiveRecord::Base)
82
- self.deleted_by_class = self.deleted_by_class.const_get(:All) if deleted_by_class_is_delete_at(self.deleted_by_class)
83
-
84
- unless reflect_on_association(:destroyer)
85
- class_eval do
86
- belongs_to :destroyer, foreign_key: deleted_by_column, primary_key: deleted_by_primary_key, class_name: deleted_by_class.name
87
- end
88
- end
45
+ def has_deleted_at_views?
46
+ ::DeletedAt::Views.all_table_exists?(self) && ::DeletedAt::Views.deleted_view_exists?(self)
89
47
  end
90
48
 
91
- def refactor_validators
92
- validators.each do |validator|
93
- case validator
94
- when ActiveRecord::Validations::UniquenessValidator
49
+ def deleted_at_attributes
50
+ attributes = {
51
+ deleted_at_column => Time.now.utc
52
+ }
95
53
 
96
- end
97
- end
98
- end
99
54
 
100
- def setup_class_views
101
- self.const_set(:All, Class.new(self) do |klass|
102
- class_eval <<-AAA
103
- self.table_name = '#{::DeletedAt::Views.all_table(klass)}'
104
- AAA
105
- end)
106
-
107
- self.const_set(:Deleted, Class.new(self) do |klass|
108
- class_eval <<-AAA
109
- self.table_name = '#{::DeletedAt::Views.deleted_view(klass)}'
110
- AAA
111
- end)
55
+ attributes
112
56
  end
113
57
 
114
- end
115
-
116
- [:archive_with_deleted_at?, :archive_with_deleted_by?].each do |sym|
117
- class_eval <<-BBB
118
- def #{sym}
119
- self.class.#{sym}
120
- end
121
- BBB
122
- end
58
+ end # End ClassMethods
123
59
 
124
60
  def destroy
125
- if archive_with_deleted_at?
61
+ if self.archive_with_deleted_at?
126
62
  with_transaction_returning_status do
127
63
  run_callbacks :destroy do
128
- update_columns(deleted_at_attributes)
64
+ update_columns(self.class.deleted_at_attributes)
129
65
  self
130
66
  end
131
67
  end
@@ -134,28 +70,33 @@ module DeletedAt
134
70
  end
135
71
  end
136
72
 
137
- private
138
-
139
- def deleted_at_attributes
140
- attributes = {
141
- deleted_at_column => Time.now.utc
142
- }
143
-
144
- # attributes.merge({
145
- # deleted_by_column => DeletedAt::who_by
146
- # }) if by_who?
147
-
148
- attributes
73
+ def self.remove_class_views(model)
74
+ model.archive_with_deleted_at = false
75
+ model.send(:remove_const, :All) if model.const_defined?(:All)
76
+ model.send(:remove_const, :Deleted) if model.const_defined?(:Deleted)
149
77
  end
150
78
 
151
- def deleted_at_column
152
- self.class.deleted_at_column
79
+ def self.parse_options(model, options)
80
+ model.deleted_at_column = (options.try(:[], :deleted_at).try(:[], :column) || :deleted_at).to_s
153
81
  end
154
82
 
155
- def deleted_by_column
156
- self.class.deleted_by_column
83
+
84
+ def self.setup_class_views(model)
85
+ model.archive_with_deleted_at = true
86
+ model.const_set(:All, Class.new(model) do |klass|
87
+ class_eval <<-AAA
88
+ self.table_name = '#{::DeletedAt::Views.all_table(klass)}'
89
+ AAA
90
+ end)
91
+
92
+ model.const_set(:Deleted, Class.new(model) do |klass|
93
+ class_eval <<-AAA
94
+ self.table_name = '#{::DeletedAt::Views.deleted_view(klass)}'
95
+ AAA
96
+ end)
157
97
  end
158
98
 
159
99
  end
100
+
160
101
  end
161
102
  end