rails_soft_deletable 0.0.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.
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Ngan Pham
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # RailsSoftDeletable
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'rails_soft_deletable'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install rails_soft_deletable
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,3 @@
1
+ module RailsSoftDeletable
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,134 @@
1
+ require "rails_soft_deletable/version"
2
+
3
+ module RailsSoftDeletable
4
+ def self.included(base)
5
+ base.extend Query
6
+ base.extend Callbacks
7
+ end
8
+
9
+ module Query
10
+ def soft_deletable?
11
+ true
12
+ end
13
+
14
+ def with_deleted
15
+ scoped.tap { |x| x.default_scoped = false }
16
+ end
17
+
18
+ def only_deleted
19
+ with_deleted.where("#{self.table_name}.#{soft_deletable_column} > 0")
20
+ end
21
+ alias :deleted :only_deleted
22
+
23
+ def restore(id)
24
+ if id.is_a?(Array)
25
+ id.map { |one_id| restore(one_id) }
26
+ else
27
+ only_deleted.find(id).restore!
28
+ end
29
+ end
30
+ end
31
+
32
+ module Callbacks
33
+ def self.extended(base)
34
+ base.define_callbacks :restore
35
+
36
+ base.define_singleton_method("before_restore") do |*args, &block|
37
+ set_callback(:restore, :before, *args, &block)
38
+ end
39
+
40
+ base.define_singleton_method("around_restore") do |*args, &block|
41
+ set_callback(:restore, :around, *args, &block)
42
+ end
43
+
44
+ base.define_singleton_method("after_restore") do |*args, &block|
45
+ set_callback(:restore, :after, *args, &block)
46
+ end
47
+ end
48
+ end
49
+
50
+ def destroy
51
+ run_callbacks(:destroy) { delete_or_soft_delete(true) }
52
+ end
53
+
54
+ def delete
55
+ return if new_record?
56
+ delete_or_soft_delete
57
+ end
58
+
59
+ def restore!
60
+ run_callbacks(:restore) do
61
+ # XXX: Rails >3.2.11 fixes an issue with update_column:
62
+ # https://github.com/rails/rails/commit/a3c3cfdd0ebba26bb9dfc0bfd4e23a5f336730c0
63
+ # Since we're on 3.2.11, we cannot use update_column.
64
+ # update_column(soft_deletable_column, 0)
65
+
66
+ name = soft_deletable_column.to_s
67
+ updated_count = self.class.unscoped.update_all({ name => 0 }, self.class.primary_key => id)
68
+ raw_write_attribute(name, 0)
69
+
70
+ updated_count == 1
71
+ end
72
+ end
73
+ alias :restore :restore!
74
+
75
+ def destroyed?
76
+ send(soft_deletable_column) && send(soft_deletable_column) > 0
77
+ end
78
+ alias :deleted? :destroyed?
79
+
80
+ private
81
+
82
+ def delete_or_soft_delete(with_transaction = false)
83
+ destroyed? ? destroy! : touch_soft_deletable_column(with_transaction)
84
+ end
85
+
86
+ def touch_soft_deletable_column(with_transaction=false)
87
+ if with_transaction
88
+ with_transaction_returning_status { touch_column }
89
+ else
90
+ touch_column
91
+ end
92
+ end
93
+
94
+ def touch_column
95
+ raise ActiveRecordError, "can not touch on a new record object" unless persisted?
96
+
97
+ current_time = current_time_from_proper_timezone.to_i
98
+ changes = {}
99
+
100
+ changes[soft_deletable_column.to_s] = write_attribute(soft_deletable_column.to_s, current_time)
101
+
102
+ changes[self.class.locking_column] = increment_lock if locking_enabled?
103
+
104
+ @changed_attributes.except!(*changes.keys)
105
+ primary_key = self.class.primary_key
106
+ self.class.unscoped.where(primary_key => self[primary_key]).update_all(changes) == 1
107
+ end
108
+ end
109
+
110
+ class ActiveRecord::Base
111
+ def self.acts_as_soft_deletable(options={})
112
+ alias :destroy! :destroy
113
+ alias :delete! :delete
114
+ include RailsSoftDeletable
115
+ class_attribute :soft_deletable_column
116
+
117
+ self.soft_deletable_column = options[:column] || :deleted_at
118
+ default_scope { where(self.quoted_table_name + ".#{soft_deletable_column} = 0") }
119
+ end
120
+
121
+ def self.soft_deletable?
122
+ false
123
+ end
124
+
125
+ def soft_deletable?
126
+ self.class.soft_deletable?
127
+ end
128
+
129
+ private
130
+
131
+ def soft_deletable_column
132
+ self.class.soft_deletable_column
133
+ end
134
+ end
@@ -0,0 +1,16 @@
1
+ require "pathname"
2
+ ROOT_PATH = Pathname.new(__FILE__).join("../..").expand_path
3
+ $LOAD_PATH.unshift(ROOT_PATH.join("lib"))
4
+
5
+ RSpec.configure do |config|
6
+ # Run specs in random order to surface order dependencies. If you find an
7
+ # order dependency and want to debug it, you can fix the order by providing
8
+ # the seed, which is printed after each run.
9
+ # --seed 1234
10
+ config.order = "random"
11
+
12
+ # Disable the should syntax compeletely; we use the expect syntax only.
13
+ config.expect_with :rspec do |c|
14
+ c.syntax = :expect
15
+ end
16
+ end
metadata ADDED
@@ -0,0 +1,117 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rails_soft_deletable
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: ruby
7
+ authors:
8
+ - Ngan Pham
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-11-21 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ version_requirements: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '1.3'
22
+ requirement: !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - ~>
26
+ - !ruby/object:Gem::Version
27
+ version: '1.3'
28
+ type: :development
29
+ prerelease: false
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ version_requirements: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ requirement: !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ version_requirements: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 3.0.0.beta1
54
+ requirement: !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ~>
58
+ - !ruby/object:Gem::Version
59
+ version: 3.0.0.beta1
60
+ type: :development
61
+ prerelease: false
62
+ - !ruby/object:Gem::Dependency
63
+ name: debugger
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: '1.6'
70
+ requirement: !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '1.6'
76
+ type: :development
77
+ prerelease: false
78
+ description: Soft deletable for ActiveRecord on Rails 3+.
79
+ email:
80
+ - ngan@listia.com
81
+ executables: []
82
+ extensions: []
83
+ extra_rdoc_files: []
84
+ files:
85
+ - lib/rails_soft_deletable/version.rb
86
+ - lib/rails_soft_deletable.rb
87
+ - spec/spec_helper.rb
88
+ - LICENSE.txt
89
+ - Rakefile
90
+ - README.md
91
+ homepage: https://github.com/listia/rails_soft_deletable
92
+ licenses:
93
+ - MIT
94
+ post_install_message:
95
+ rdoc_options: []
96
+ require_paths:
97
+ - lib
98
+ required_ruby_version: !ruby/object:Gem::Requirement
99
+ none: false
100
+ requirements:
101
+ - - ! '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ required_rubygems_version: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ requirements: []
111
+ rubyforge_project:
112
+ rubygems_version: 1.8.25
113
+ signing_key:
114
+ specification_version: 3
115
+ summary: Soft deletable for ActiveRecord on Rails 3+
116
+ test_files:
117
+ - spec/spec_helper.rb