mark_only 0.0.2 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/README.md +20 -19
- data/Rakefile +12 -8
- data/lib/mark_only/version.rb +1 -1
- data/lib/mark_only.rb +108 -31
- metadata +21 -23
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
NmQxYjJjY2RlMjFhM2EzYTg2MjdlYjkyOWRmYjMwZmQxZTZkMTBiOA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
Y2Y1MWM5ZjgyOGI1YTcyZGJhZmJjNWVmZmQ4ZDAxNzE1ZDk4NDViMA==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
YjBlODY0NmU1MWMxM2JmNTdiNTY5ZmRhMmI4ZTE2ZDRlYjhiZTExMjc4NDgz
|
10
|
+
MDUyNDJmYTdiYTJhNDdjMDA2NmE4ODk4N2UxZTdmNjBkMmJlZmYxODFhMGQ4
|
11
|
+
MzI5YjhkYmRmMjU4ZTM1ZTU4Mjk2ZWU2MjExNzE4NGNjZmQyYzQ=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
YjdjOGViMjkwNGFjNTJhMDMzOTZkMTNiYWRhYWRiYzg4NWNlNTYwNTNkNTkz
|
14
|
+
OTE1YTRkMmIzMTgyNTE4MjBhYjFiYTg4NGY5NDQ4ODNhZWIzMzk4ZTFlZTMz
|
15
|
+
ODRkN2I1YzYyMDA5MzcyMzdmN2E4MmNjNmQ1NjM5NTNmNjZmYWI=
|
data/README.md
CHANGED
@@ -1,10 +1,16 @@
|
|
1
|
+
[![Build Status](https://secure.travis-ci.org/FineLinePrototyping/mark_only.png?branch=master)][travis] [![Gem Version](https://badge.fury.io/rb/mark_only.png)][badgefury]
|
2
|
+
|
1
3
|
# Mark Only
|
2
4
|
|
3
|
-
|
5
|
+
Want to only mark a column with a value when the record is deleted or destroyed, but not unscope it? Then you're in the right place. If you want the records to be out of scope, look at acts_as_paranoid, paranoid, etc.
|
6
|
+
|
7
|
+
`mark_only` on the model class sets a specified column with a specified value on destroy/delete and disables the ability to `delete`/`destroy` on instance, model class, and via relation, using the default ActiveRecord version of those, and supports destroy callbacks if raise not enabled. `destroy!` in Rails 4 is supported.
|
4
8
|
|
5
|
-
|
9
|
+
Once a record is marked, `deleted?`/`destroyed?` methods on a retrieved model instance return false.
|
6
10
|
|
7
|
-
|
11
|
+
Tested with ActiveRecord 3.1.x, 3.2.x, and 4.0.x via travis and appraisal.
|
12
|
+
|
13
|
+
Code originally based on [Paranoia][paranoia] (by Ryan Bigg and others), but heavily modified.
|
8
14
|
|
9
15
|
## Installation & Usage
|
10
16
|
|
@@ -44,7 +50,9 @@ Use the active_value as `:default`.
|
|
44
50
|
|
45
51
|
```ruby
|
46
52
|
MarkOnly.configure do
|
47
|
-
|
53
|
+
# if true, debug log failed attempts to delete/destroy
|
54
|
+
self.debug = false
|
55
|
+
# the value that should indicate that a record is deleted
|
48
56
|
self.deleted_value = 'deleted'
|
49
57
|
end
|
50
58
|
|
@@ -53,6 +61,8 @@ end
|
|
53
61
|
|
54
62
|
#### In your model:
|
55
63
|
|
64
|
+
To disallow attempts to delete/destroy and instead update the specified column:
|
65
|
+
|
56
66
|
```ruby
|
57
67
|
class Client < ActiveRecord::Base
|
58
68
|
mark_only :some_column_to_mark
|
@@ -61,24 +71,15 @@ class Client < ActiveRecord::Base
|
|
61
71
|
end
|
62
72
|
```
|
63
73
|
|
64
|
-
|
65
|
-
|
66
|
-
```ruby
|
67
|
-
class Client < ActiveRecord::Base
|
68
|
-
mark_only :some_column_to_mark
|
69
|
-
|
70
|
-
before_destroy :some_method
|
71
|
-
|
72
|
-
def some_method
|
73
|
-
# do stuff
|
74
|
-
end
|
74
|
+
## Upgrading
|
75
75
|
|
76
|
-
|
77
|
-
end
|
78
|
-
```
|
76
|
+
* v0.0.1 -> v1.0.x: `restore!` no longer supported; the workaround is to use SQL to change a record's mark column to some value other than MarkOnly.deleted_value. Similarly, if you need to really delete or destroy a row in the database corresponding to the record, use SQL.
|
79
77
|
|
80
78
|
## License
|
81
79
|
|
82
|
-
This gem is released under the MIT license.
|
80
|
+
This gem is released under the [MIT license][lic].
|
83
81
|
|
82
|
+
[lic]: http://github.com/FineLinePrototyping/mark_only/blob/master/LICENSE
|
84
83
|
[paranoia]: https://github.com/radar/paranoia
|
84
|
+
[travis]: http://travis-ci.org/FineLinePrototyping/mark_only
|
85
|
+
[badgefury]: http://badge.fury.io/rb/mark_only
|
data/Rakefile
CHANGED
@@ -1,11 +1,15 @@
|
|
1
|
-
require 'bundler'
|
2
|
-
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'bundler/gem_tasks'
|
3
|
+
require 'appraisal'
|
3
4
|
|
4
|
-
task :
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
task :default do |t|
|
6
|
+
if ENV['BUNDLE_GEMFILE'] =~ /gemfiles/
|
7
|
+
load 'test/mark_only_test.rb'
|
8
|
+
else
|
9
|
+
exec 'bundle install && bundle exec rake appraise'
|
10
|
+
end
|
9
11
|
end
|
10
12
|
|
11
|
-
task :
|
13
|
+
task :appraise => ['appraisal:install'] do |t|
|
14
|
+
exec 'bundle install && bundle exec rake appraisal'
|
15
|
+
end
|
data/lib/mark_only/version.rb
CHANGED
data/lib/mark_only.rb
CHANGED
@@ -2,34 +2,46 @@ require 'mark_only/version'
|
|
2
2
|
|
3
3
|
module MarkOnly
|
4
4
|
class << self
|
5
|
-
|
6
|
-
def configure(&blk)
|
5
|
+
attr_accessor :debug, :deleted_value
|
6
|
+
def configure(&blk)
|
7
|
+
class_eval(&blk)
|
8
|
+
end
|
7
9
|
end
|
8
10
|
|
9
|
-
|
10
|
-
klazz.extend Query
|
11
|
-
end
|
11
|
+
extend ActiveSupport::Concern
|
12
12
|
|
13
|
-
module
|
14
|
-
def mark_only?
|
13
|
+
module ClassMethods
|
14
|
+
def mark_only?
|
15
|
+
true
|
16
|
+
end
|
17
|
+
|
18
|
+
def delete(id_or_array)
|
19
|
+
logger.debug("will not #{self}.delete #{id_or_array.inspect}", e) if MarkOnly.debug
|
20
|
+
c = "#{quoted_table_name}.#{connection.quote_column_name self.mark_only_column}"
|
21
|
+
self.
|
22
|
+
where(primary_key => id_or_array).
|
23
|
+
where("#{c} != ? OR #{c} IS NULL", MarkOnly.deleted_value).
|
24
|
+
update_all({self.mark_only_column => MarkOnly.deleted_value})
|
25
|
+
end
|
26
|
+
|
27
|
+
def delete_all(conditions = nil)
|
28
|
+
logger.debug("will not #{self}.delete_all", e) if MarkOnly.debug
|
29
|
+
c = "#{quoted_table_name}.#{connection.quote_column_name self.mark_only_column}"
|
30
|
+
(conditions ? self.where(conditions) : self).
|
31
|
+
where("#{c} != ? OR #{c} IS NULL", MarkOnly.deleted_value).
|
32
|
+
update_all({self.mark_only_column => MarkOnly.deleted_value})
|
33
|
+
end
|
15
34
|
end
|
16
35
|
|
17
36
|
def destroy
|
37
|
+
logger.debug("will not delete #{self}", e) if MarkOnly.debug
|
38
|
+
update_mark_only_attribute_or_column(self.mark_only_column, MarkOnly.deleted_value) if !deleted? && persisted?
|
18
39
|
run_callbacks(:destroy) { delete }
|
19
40
|
end
|
20
|
-
|
41
|
+
|
21
42
|
def delete
|
22
|
-
|
23
|
-
|
24
|
-
logger.error("failed to set #{self.mark_only_column} to #{MarkOnly.deleted_value} in #{self}", e)
|
25
|
-
raise e
|
26
|
-
end
|
27
|
-
|
28
|
-
def restore!
|
29
|
-
update_attribute_or_column self.mark_only_column, MarkOnly.active_value
|
30
|
-
rescue => e
|
31
|
-
logger.error("failed to set #{self.mark_only_column} to #{MarkOnly.active_value} in #{self}", e)
|
32
|
-
raise e
|
43
|
+
logger.debug("will not delete #{self}", e) if MarkOnly.debug
|
44
|
+
update_mark_only_attribute_or_column(self.mark_only_column, MarkOnly.deleted_value) if !deleted? && persisted?
|
33
45
|
end
|
34
46
|
|
35
47
|
def destroyed?
|
@@ -37,36 +49,101 @@ module MarkOnly
|
|
37
49
|
end
|
38
50
|
alias :deleted? :destroyed?
|
39
51
|
|
40
|
-
|
52
|
+
end
|
41
53
|
|
42
|
-
|
43
|
-
|
44
|
-
|
54
|
+
module MarkOnlyRails4Extensions
|
55
|
+
extend ActiveSupport::Concern
|
56
|
+
|
57
|
+
def destroy!
|
58
|
+
update_mark_only_attribute_or_column(self.mark_only_column, MarkOnly.deleted_value) if !deleted? && persisted?
|
59
|
+
raise ActiveRecord::RecordNotDestroyed.new("#{self} is mark_only")
|
45
60
|
end
|
46
61
|
end
|
47
62
|
|
48
63
|
MarkOnly.configure do
|
49
|
-
self.
|
64
|
+
self.debug = false
|
50
65
|
self.deleted_value = 'deleted'
|
51
66
|
end
|
52
67
|
|
68
|
+
class ActiveRecord::Relation
|
69
|
+
# don't use generic naming to try to avoid conflicts, since this isn't model class specific
|
70
|
+
alias_method :mark_only_orig_relation_delete_all, :delete_all
|
71
|
+
def delete_all(*args, &block)
|
72
|
+
if klass.respond_to?(:mark_only?) && klass.mark_only?
|
73
|
+
logger.debug("will not #{self}.delete_all", e) if MarkOnly.debug
|
74
|
+
if args.length > 0 && block_given?
|
75
|
+
where(*args, &block)
|
76
|
+
elsif args.length > 0 && !block_given?
|
77
|
+
where(*args)
|
78
|
+
elsif args.length == 0 && block_given?
|
79
|
+
where(&block)
|
80
|
+
end
|
81
|
+
c = "#{quoted_table_name}.#{connection.quote_column_name self.mark_only_column}"
|
82
|
+
where("#{c} != ? OR #{c} IS NULL", MarkOnly.deleted_value)
|
83
|
+
update_all({self.mark_only_column => MarkOnly.deleted_value})
|
84
|
+
else
|
85
|
+
mark_only_orig_relation_delete_all(*args, &block)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# don't use generic naming to try to avoid conflicts, since this isn't model class specific
|
90
|
+
alias_method :mark_only_orig_relation_destroy_all, :destroy_all
|
91
|
+
def destroy_all(*args, &block)
|
92
|
+
if klass.respond_to?(:mark_only?) && klass.mark_only?
|
93
|
+
logger.debug("will not #{self}.destroy_all", e) if MarkOnly.debug
|
94
|
+
if args.length > 0 && block_given?
|
95
|
+
where(*args, &block)
|
96
|
+
elsif args.length > 0 && !block_given?
|
97
|
+
where(*args)
|
98
|
+
elsif args.length == 0 && block_given?
|
99
|
+
where(&block)
|
100
|
+
end
|
101
|
+
c = "#{quoted_table_name}.#{connection.quote_column_name self.mark_only_column}"
|
102
|
+
where("#{c} != ? OR #{c} IS NULL", MarkOnly.deleted_value)
|
103
|
+
update_all({self.mark_only_column => MarkOnly.deleted_value})
|
104
|
+
#rel.to_a.each {|object| object.run_callbacks(:destroy) { delete }}.tap { reset }
|
105
|
+
else
|
106
|
+
mark_only_orig_relation_destroy_all(*args, &block)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
53
111
|
class ActiveRecord::Base
|
112
|
+
|
54
113
|
def self.mark_only(col_name)
|
55
114
|
raise "#{self} must call mark_only with a column name!" unless col_name
|
56
115
|
class_attribute :mark_only_column, instance_writer: true
|
57
116
|
self.mark_only_column = col_name.to_sym
|
58
|
-
|
59
|
-
|
117
|
+
class << self
|
118
|
+
alias_method :mark_only_orig_class_delete, :delete
|
119
|
+
alias_method :mark_only_orig_class_delete_all, :delete_all
|
120
|
+
end
|
121
|
+
alias_method :mark_only_orig_delete, :delete
|
122
|
+
alias_method :mark_only_orig_destroy, :destroy
|
60
123
|
include MarkOnly
|
124
|
+
if defined?(ActiveRecord::VERSION::MAJOR) && ActiveRecord::VERSION::MAJOR > 3
|
125
|
+
alias_method :mark_only_orig_destroy!, :destroy!
|
126
|
+
include MarkOnlyRails4Extensions
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def self.mark_only?
|
131
|
+
false
|
61
132
|
end
|
62
133
|
|
63
|
-
def
|
64
|
-
|
134
|
+
def mark_only?
|
135
|
+
self.class.mark_only?
|
136
|
+
end
|
65
137
|
|
66
|
-
# Override the persisted method to allow for the paranoia gem.
|
67
|
-
# If a mark_only record is selected, then we only want to check
|
68
|
-
# if it's a new record, not if it is "destroyed".
|
69
138
|
def persisted?
|
70
139
|
mark_only? ? !new_record? : super
|
71
140
|
end
|
141
|
+
|
142
|
+
private
|
143
|
+
|
144
|
+
# Rails 3.1 adds update_column. Rails > 3.2.6 deprecates update_attribute, gone in Rails 4.
|
145
|
+
def update_mark_only_attribute_or_column(*args)
|
146
|
+
respond_to?(:update_column) ? update_column(*args) : update_attribute(*args)
|
147
|
+
end
|
148
|
+
|
72
149
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mark_only
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gary S. Weaver
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-07-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -16,42 +16,42 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ! '>='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 3.
|
19
|
+
version: '3.1'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ! '>='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 3.
|
26
|
+
version: '3.1'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: activesupport
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ! '>='
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 3.
|
34
|
-
type: :
|
33
|
+
version: '3.1'
|
34
|
+
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - ! '>='
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 3.
|
40
|
+
version: '3.1'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: appraisal
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - ! '>='
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
47
|
+
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
54
|
+
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: sqlite3
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -67,22 +67,21 @@ dependencies:
|
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: bundler
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - '
|
73
|
+
- - ! '>='
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: 0
|
75
|
+
version: '0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- - '
|
80
|
+
- - ! '>='
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: 0
|
83
|
-
description:
|
84
|
-
|
85
|
-
hooks.
|
82
|
+
version: '0'
|
83
|
+
description: Updates a specified column with an pre-configured value on delete/destroy.
|
84
|
+
Supports destroy hooks.
|
86
85
|
email:
|
87
86
|
- garysweaver@gmail.com
|
88
87
|
executables: []
|
@@ -93,7 +92,7 @@ files:
|
|
93
92
|
- lib/mark_only.rb
|
94
93
|
- Rakefile
|
95
94
|
- README.md
|
96
|
-
homepage: https://github.com/
|
95
|
+
homepage: https://github.com/FineLinePrototyping/mark_only
|
97
96
|
licenses:
|
98
97
|
- MIT
|
99
98
|
metadata: {}
|
@@ -113,9 +112,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
113
112
|
version: 1.3.6
|
114
113
|
requirements: []
|
115
114
|
rubyforge_project:
|
116
|
-
rubygems_version: 2.0.
|
115
|
+
rubygems_version: 2.0.6
|
117
116
|
signing_key:
|
118
117
|
specification_version: 4
|
119
|
-
summary:
|
120
|
-
with an pre-configured value on delete/destroy.
|
118
|
+
summary: Updates a specified column with an pre-configured value on delete/destroy.
|
121
119
|
test_files: []
|