on_destroy 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,62 @@
1
+ on_destroy
2
+ =====
3
+
4
+ This is a Rails 3.x ActiveRecord enhancement that allows you to:
5
+ * use `:do_not_delete` option to not call the delete callback on destroy by sending an empty block to `run_callbacks(:destroy)`.
6
+ * use `:set_column` to specify the column to update.
7
+ * use `:to` to specify the value to set the column to.
8
+
9
+ So, basically it will let you update a column/attribute of a model without actually deleting the record.
10
+
11
+ Also take a look at [acts_as_paranoid][acts_as_paranoid] [rails3_acts_as_paranoid][rails3_acts_as_paranoid], [soft_destroyable][soft_destroyable], [paranoia][paranoia], and other similar gems to be sure this is what you are looking for. The difference is that this gem does nothing with scoping, it just lets you mark a record as deleted without deleting it when you call destroy. This is just meant to provide a shortcut and slight safeguard in the situations where you want the client side to do the filtering of deleted records so that you can retain references to old models and maybe just color them differently in the UI to indicate that they are no longer active.
12
+
13
+ Add to your Gemfile:
14
+
15
+ gem 'on_destroy'
16
+
17
+ Then run:
18
+
19
+ bundle install
20
+
21
+ In your model you could include one of the following. You must ensure that the column exists and supports the value you are trying to set on it:
22
+
23
+ on_destroy :do_not_delete, set: :some_column, to: 'some string value'
24
+ on_destroy :do_not_delete, set: :some_column, to: nil
25
+ on_destroy :do_not_delete, set: :some_column, to: false
26
+ on_destroy :do_not_delete, set: :some_column, to: 1
27
+ on_destroy :do_not_delete, set: :some_column, to: lambda {Time.now}
28
+
29
+ Something similar to light version of rails3_acts_as_paranoid could be produced by the following (note: default_scope is not implemented or affected by this plugin, I'm just using it for an example):
30
+
31
+ default_scope where("deleted_at IS NOT NULL")
32
+ on_destroy :do_not_delete, set: :deleted_at, to: lambda {Time.now}
33
+
34
+ Do on_destroy for all models with:
35
+
36
+ # Do it for everything
37
+ OnDestroy.configure do
38
+ self.do_not_delete = true
39
+ self.set = [:deleted]
40
+ self.to = true
41
+ end
42
+
43
+ If you want control over how it intuits how something is deleted (which is to look at the deleted date) use `:is_deleted_if` which can be a value, nil, or a Proc that takes the attribute value:
44
+
45
+ on_destroy :do_not_delete, set: :some_column, to: lambda {Time.now}, is_deleted_if: {|c|Time.now > c} # provide time-travel resistent behavior of destroyed?/deleted?
46
+ on_destroy :do_not_delete, set: :some_column, to: 1 is_deleted_if: 1 # this is not necessary, as it will already check for 1 since you specified it in the :to
47
+
48
+ If you use a proc to set the value and a value of nil indicates that it should be deleted (which is kind of wierd), you'll need to set:
49
+
50
+ on_destroy :do_not_delete, set: :some_column, to: lambda {nil} is_deleted_if: nil
51
+
52
+ To call a normal-ish `destroy` method, use the `really_destroy` method. I think this is better than using `destroy!` because all of the other bang methods on ActiveRecord.base tend to just throw errors, not behave that differently, despite the `destroy!` method being a naming convention from acts_as_paranoid.
53
+
54
+ ### License
55
+
56
+ Copyright (c) 2012 Gary S. Weaver, released under the [MIT license][lic].
57
+
58
+ [paranoia]: https://github.com/radar/paranoia
59
+ [soft_destroyable]: https://github.com/rockrep/soft_destroyable
60
+ [acts_as_paranoid]: http://github.com/technoweenie/acts_as_paranoid
61
+ [rails3_acts_as_paranoid]: https://github.com/goncalossilva/rails3_acts_as_paranoid
62
+ [lic]: http://github.com/garysweaver/on_destroy/blob/master/LICENSE
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require 'rake/testtask'
2
+
3
+ #http://nicksda.apotomo.de/2010/10/testing-your-rails-3-engine-sitting-in-a-gem/
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << 'test'
6
+ t.test_files = FileList['test/**/*_test.rb']
7
+ t.verbose = true
8
+ end
9
+
10
+ desc "Run tests"
11
+ task :default => :test
@@ -0,0 +1,20 @@
1
+ module OnDestroy
2
+ OPTIONS = [
3
+ :do_not_delete,
4
+ :set,
5
+ :to,
6
+ :is_deleted_if
7
+ ]
8
+
9
+ class << self
10
+ OPTIONS.each{|o|attr_accessor o; define_method("#{o}?".to_sym){!!send("#{o}")}}
11
+ def configure(&blk); class_eval(&blk); end
12
+ end
13
+ end
14
+
15
+ # Do it for everything
16
+ #OnDestroy.configure do
17
+ # self.do_not_delete = true
18
+ # self.set = [:deleted]
19
+ # self.to = true
20
+ #end
@@ -0,0 +1,81 @@
1
+ module OnDestroy
2
+ module Model
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ class_attribute :defined_is_deleted_if
7
+ # use values from config
8
+ OnDestroy::OPTIONS.each do |key|
9
+ class_attribute key, instance_writer: true
10
+ self.send("#{key}=".to_sym, OnDestroy.send(key))
11
+ end
12
+ around_destroy :do_on_destroy
13
+ end
14
+
15
+ module ClassMethods
16
+ # a shortcut to set configuration:
17
+ # self.do_not_delete, self.set, self.to, self.is_deleted_if
18
+ # and to default self.is_deleted_if to a proc that
19
+ def on_destroy(*args)
20
+ options = args.extract_options!
21
+ self.do_not_delete = true if args.include?(:do_not_delete)
22
+ self.set = options[:set] if options[:set]
23
+ self.to = options[:to] if options[:to]
24
+ if options[:is_deleted_if]
25
+ # set defined_is_deleted_if to allow explicit set to nil
26
+ self.defined_is_deleted_if = true
27
+ self.is_deleted_if = options[:is_deleted_if]
28
+ elsif (options[:to].is_a?(Proc))
29
+ # if :to is a Proc, assume that a nil value means it is not deleted and if not-nil is deleted.
30
+ # that is just a guess, based on the mark with deleted_at date example.
31
+ self.is_deleted_if = Proc.new {|v| v != nil}
32
+ else
33
+ self.is_deleted_if = Proc.new {|v| v == send(options[:to])}
34
+ end
35
+ end
36
+ end
37
+
38
+ # Instance methods
39
+
40
+ # if self.set then will use update_attributes! to set the self.set attribute to self.to or self.to.call if it is a Proc.
41
+ def do_on_destroy
42
+ if self.set
43
+ to_value = self.to.is_a?(Proc) ? self.to.call : self.to
44
+ update_attributes! self.set => to_value
45
+ end
46
+ yield
47
+ end
48
+
49
+ # if self.do_not_delete? runs no/empty callback on :destroy, otherwise calls super.
50
+ def destroy
51
+ if self.do_not_delete?
52
+ # don't destroy
53
+ run_callbacks(:destroy) {}
54
+ else
55
+ # destroy
56
+ super
57
+ end
58
+ end
59
+
60
+ # runs delete callback on :destroy
61
+ def really_destroy
62
+ run_callbacks(:destroy) {delete}
63
+ end
64
+
65
+ # if self.is_deleted_if is a Proc compares self.is_deleted_if.call to send(self.to).
66
+ # if self.is_deleted_if is not nil compares self.is_deleted_if.call to send(self.to).
67
+ # If self.is_deleted_if not a Proc, calls super.
68
+ def destroyed?
69
+ if self.is_deleted_if.is_a?(Proc)
70
+ self.is_deleted_if.call(send(self.to))
71
+ elsif self.is_deleted_if.nil? && !(self.defined_is_deleted_if == true)
72
+ # will default to super only if self.is_deleted_if not defined by user
73
+ super
74
+ else
75
+ self.is_deleted_if == send(self.to)
76
+ end
77
+ end
78
+
79
+ alias_method :deleted?, :destroyed?
80
+ end
81
+ end
@@ -0,0 +1,12 @@
1
+ require 'on_destroy'
2
+
3
+ module OnDestroy
4
+ class Railtie < Rails::Railtie
5
+ initializer "on_destroy.active_record" do
6
+ ActiveSupport.on_load(:active_record) do
7
+ # ActiveRecord::Base gets new behavior
8
+ include OnDestroy::Model
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,3 @@
1
+ module OnDestroy
2
+ VERSION = '0.0.1'
3
+ end
data/lib/on_destroy.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'on_destroy/version'
2
+ require 'on_destroy/config'
3
+ require 'on_destroy/model'
4
+ require 'on_destroy/railtie' if defined?(Rails)
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: on_destroy
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Gary S. Weaver
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-10-08 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activerecord
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ description: Change ActiveModel's destroy behavior.
31
+ email:
32
+ - garysweaver@gmail.com
33
+ executables: []
34
+ extensions: []
35
+ extra_rdoc_files: []
36
+ files:
37
+ - lib/on_destroy/config.rb
38
+ - lib/on_destroy/model.rb
39
+ - lib/on_destroy/railtie.rb
40
+ - lib/on_destroy/version.rb
41
+ - lib/on_destroy.rb
42
+ - Rakefile
43
+ - README.md
44
+ homepage: https://github.com/garysweaver/on_destroy
45
+ licenses:
46
+ - MIT
47
+ post_install_message:
48
+ rdoc_options: []
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ! '>='
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ requirements: []
64
+ rubyforge_project:
65
+ rubygems_version: 1.8.24
66
+ signing_key:
67
+ specification_version: 3
68
+ summary: Change destroy's behavior.
69
+ test_files: []