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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- YjUxYmFlNWJjMzA1M2VmYzA5MTYxNWQyYzVhZjI2MjI1ODk2MGMyZQ==
4
+ NmQxYjJjY2RlMjFhM2EzYTg2MjdlYjkyOWRmYjMwZmQxZTZkMTBiOA==
5
5
  data.tar.gz: !binary |-
6
- MzAzM2Q3ZGFjYzgyZjVmMGFkYzIxNmM4YjhhMTMxMGUwYjRlNWE4Mg==
6
+ Y2Y1MWM5ZjgyOGI1YTcyZGJhZmJjNWVmZmQ4ZDAxNzE1ZDk4NDViMA==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- Y2ZiODM2NWMwOThjNzhjYWFhYTE2NWM3MDdiYmYwYWM2YmNkNzE4ZDVjMGYz
10
- ZTU5MDc5NjAyYWVmNDljZWJiYjgyODRhMTgxZDliY2JhZjEzMjVlNTlhNjA2
11
- ODg3MWVkN2JhMmE5OWZlMWY0ODNkNWNhMzUzYzBlMGU3YmQzZDA=
9
+ YjBlODY0NmU1MWMxM2JmNTdiNTY5ZmRhMmI4ZTE2ZDRlYjhiZTExMjc4NDgz
10
+ MDUyNDJmYTdiYTJhNDdjMDA2NmE4ODk4N2UxZTdmNjBkMmJlZmYxODFhMGQ4
11
+ MzI5YjhkYmRmMjU4ZTM1ZTU4Mjk2ZWU2MjExNzE4NGNjZmQyYzQ=
12
12
  data.tar.gz: !binary |-
13
- ZWNkNGU1YjZhNWNiZjE2NzhjZDZjOTY1ZTIzOThjMzYzNDI2NzNjNjcwNGU0
14
- ZGE1NDFhZGZmYmYyNWY4OTI5M2Q1NTA4MWNjYzU0N2Q3M2ZjN2I4MTBlZjdh
15
- YmI4ZDA3MGQ5NmYxODg3MzQ4MDgwNzU4YzZiZTQyNGVkNzk3ZTM=
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
- Mark Only is a fork of [Paranoia][paranoia] (by Ryan Bigg and others) with significant changes. It only sets a specified column with a specified value on destroy/delete. Like Paranoia it allows before_destroy, etc. callbacks.
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
- However, it does not unscope marked records. This means that anything that attempts to find the record after a destroy will still find it.
9
+ Once a record is marked, `deleted?`/`destroyed?` methods on a retrieved model instance return false.
6
10
 
7
- To *really* destroy or delete records, use the Paranoia/acts_as_paranoid convention of calling `destroy!` or `delete!`.
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
- self.active_value = 'active'
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
- If you want a method to be called on destroy, simply provide a _before\_destroy_ callback:
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
- Bundler::GemHelper.install_tasks
1
+ require 'bundler/setup'
2
+ require 'bundler/gem_tasks'
3
+ require 'appraisal'
3
4
 
4
- task :test do
5
- load 'test/mark_only_test.rb'
6
- #Dir['test/*_test.rb'].each do |testfile|
7
- # load testfile
8
- #end
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 :default => :test
13
+ task :appraise => ['appraisal:install'] do |t|
14
+ exec 'bundle install && bundle exec rake appraisal'
15
+ end
@@ -1,3 +1,3 @@
1
1
  module MarkOnly
2
- VERSION = "0.0.2"
2
+ VERSION = "1.0.1"
3
3
  end
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
- [:deleted_value, :active_value].each{|o|attr_accessor o}
6
- def configure(&blk); class_eval(&blk); end
5
+ attr_accessor :debug, :deleted_value
6
+ def configure(&blk)
7
+ class_eval(&blk)
8
+ end
7
9
  end
8
10
 
9
- def self.included(klazz)
10
- klazz.extend Query
11
- end
11
+ extend ActiveSupport::Concern
12
12
 
13
- module Query
14
- def mark_only? ; true ; end
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
- update_attribute_or_column(self.mark_only_column, MarkOnly.deleted_value) if !deleted? && persisted?
23
- rescue => e
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
- private
52
+ end
41
53
 
42
- # Rails 3.1 adds update_column. Rails > 3.2.6 deprecates update_attribute, gone in Rails 4.
43
- def update_attribute_or_column(*args)
44
- respond_to?(:update_column) ? update_column(*args) : update_attribute(*args)
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.active_value = 'active'
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
- alias :destroy! :destroy
59
- alias :delete! :delete
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 self.mark_only? ; false ; end
64
- def mark_only? ; self.class.mark_only? ; end
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: 0.0.2
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-04-18 00:00:00.000000000 Z
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.0.0
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.0.0
26
+ version: '3.1'
27
27
  - !ruby/object:Gem::Dependency
28
- name: activerecord
28
+ name: activesupport
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ! '>='
32
32
  - !ruby/object:Gem::Version
33
- version: 3.0.0
34
- type: :development
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.0.0
40
+ version: '3.1'
41
41
  - !ruby/object:Gem::Dependency
42
- name: bundler
42
+ name: appraisal
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ! '>='
46
46
  - !ruby/object:Gem::Version
47
- version: 1.0.0
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: 1.0.0
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: rake
70
+ name: bundler
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - '='
73
+ - - ! '>='
74
74
  - !ruby/object:Gem::Version
75
- version: 0.8.7
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.8.7
83
- description: A fork of Paranoia (by Ryan Bigg and others) that updates a specified
84
- column with an pre-configured value on destroy, and does no scoping. Supports destroy
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/garysweaver/mark_only
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.3
115
+ rubygems_version: 2.0.6
117
116
  signing_key:
118
117
  specification_version: 4
119
- summary: A fork of Paranoia (by Ryan Bigg and others) that updates a specified column
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: []