kakurenbo 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9d17f226c87b76328e3f11a74e9224af2c25ec7d
4
- data.tar.gz: 85ecc8c56e701cf1500416a969733c6bb098c1e6
3
+ metadata.gz: d0eed74f6f1f4ee3e648f8d23f196b017a3933a0
4
+ data.tar.gz: 9aba55b5f4d2191702e64feecfc348051fff0ad2
5
5
  SHA512:
6
- metadata.gz: 28c44c302564b18f8930dac1a90553e83c8bbbf0a3186575eafce1898a75e8902a88c3f0d1a06f02d0064ab3a61e37e1ef6d7bbd1a9ee9bf32a57d3ba7c2f4fa
7
- data.tar.gz: 44d3f77630f0872526c21d94761f81e98dbe5e52f43de9e3e7e97fec8ed09f1bc5d8a9b5bfc95096ceebc8b901ef36227316dbfc008d0497db8eb07db48b99f0
6
+ metadata.gz: dd0dc2d6abe2a70959bb5fdabcdf3b6970d24530208538c19af5e4d38f570f360a593a506f53ea867801f3bbb57a54ac005a45cdd711e973824888c4a2974e72
7
+ data.tar.gz: a0305a8d5be99ea68c939dbd8a3e279548b8cd39e87ee14fe6c1c017655e4e87a734695b19b6c890cf0efc4b5866a8ff45bf252cca1afb53500c5b63c10572ec
@@ -6,6 +6,5 @@ rvm:
6
6
  - 1.9.3
7
7
  - 2.1.0
8
8
  env:
9
- - RAILS=3.2.16
10
- - RAILS=4.0.2
11
- - RAILS=4.1.0
9
+ - ACTIVE_RECORD_VERSION='~> 4.0.2'
10
+ - ACTIVE_RECORD_VERSION='~> 4.1.0'
data/Gemfile CHANGED
@@ -1,4 +1,8 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
+ if ENV['ACTIVE_RECORD_VERSION']
4
+ gem 'activerecord', ENV['ACTIVE_RECORD_VERSION']
5
+ end
6
+
3
7
  # Specify your gem's dependencies in kakurenbo.gemspec
4
8
  gemspec
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Kakurenbo
2
2
 
3
3
  Kakurenbo provides soft delete.
4
- Kakurenbo is a re-implementation of [paranoia](http://github.com/radar/paranoia) and [acts\_as\_paranoid](http://github.com/technoweenie/acts_as_paranoid) for Rails4 and 3. implemented a function that other gems are not enough.
4
+ Kakurenbo is a re-implementation of [paranoia](http://github.com/radar/paranoia) and [acts\_as\_paranoid](http://github.com/technoweenie/acts_as_paranoid) for Rails4. implemented a function that other gems are not enough.
5
5
 
6
6
  The usage of the Kakurenbo is very very very simple. Only add `deleted_at`(datetime) to column.
7
7
  Of course you can use `acts_as_paranoid`.In addition, Kakurenbo has many advantageous.
@@ -30,38 +30,50 @@ _Kakurenbo provides `acts_as_paranoid` method for compatibility._
30
30
  ### soft-delete
31
31
 
32
32
  ``` ruby
33
+ # if action is cancelled by callbacks, return false.
33
34
  model.destroy
34
35
 
35
- # This is usable, too.
36
- Model.destroy(id)
37
- Model.destroy([id1,id2,id3])
36
+ # if action is cancelled by callbacks, raise ActiveRecord::RecordNotDestroyed.
37
+ model.destroy!
38
+
39
+ # selected model will be destroyed.
40
+ Model.where(:foo => 'bar').destroy_all
38
41
  ```
39
42
 
40
43
  when want without callbacks.
41
44
 
42
45
  ``` ruby
43
46
  model.delete
47
+
48
+ # selected model will be deleted.
49
+ Model.where(:foo => 'bar').delete_all
44
50
  ```
45
51
 
46
52
  ### restore a record
47
53
 
48
54
  ``` ruby
49
- model.restore!
55
+ # if action is cancelled by callbacks, return false.
56
+ model.restore
50
57
 
51
- # This is usable, too.
52
- Model.restore(id)
53
- Model.restore([id1,id2,id3])
58
+ # if action is cancelled by callbacks, raise ActiveRecord::RecordNotRestored.
59
+ model.restore!
54
60
  ```
55
-
56
61
  When restore, call restore callbacks.`before_restore` `after_restore`
57
62
 
58
63
 
59
64
  ### hard-delete
65
+ Use hard option.
66
+ ``` ruby
67
+ model.destroy(hard: true)
60
68
 
69
+ # without callbacks.
70
+ model.delete(hard: true)
61
71
 
62
- ``` ruby
63
- model = Model.new
64
- model.destroy!
72
+ # selected model will be destroyed.
73
+ Model.where(:foo => 'bar').destroy_all(nil, hard: true)
74
+
75
+ # selected model will be destroyed.
76
+ Model.where(:foo => 'bar').delete_all(nil, hard: true)
65
77
  ```
66
78
 
67
79
  ### check if a record is fotdeleted
@@ -34,9 +34,9 @@ Gem::Specification.new do |spec|
34
34
 
35
35
  spec.add_development_dependency "bundler", "~> 1.5"
36
36
  spec.add_development_dependency "rake"
37
- spec.add_development_dependency "rspec"
37
+ spec.add_development_dependency "rspec", ">= 3.0.0"
38
38
  spec.add_development_dependency "yard"
39
39
  spec.add_development_dependency "sqlite3"
40
40
 
41
- spec.add_dependency 'activerecord', '>= 3.2.0'
41
+ spec.add_dependency 'activerecord', '>= 4.0.2'
42
42
  end
@@ -5,7 +5,14 @@ require "active_record"
5
5
  # require kakurenbo modules.
6
6
  require "kakurenbo/version"
7
7
  require "kakurenbo/mixin_ar_base"
8
- require "kakurenbo/soft_delete_core"
8
+ require "kakurenbo/mixin_ar_relation"
9
+ require "kakurenbo/core"
10
+
11
+ # Kakurenbo Add ActiveRecord::RecordNotRestored to ActiveRecord
12
+ class ActiveRecord::RecordNotRestored < ActiveRecord::RecordNotDestroyed; end
9
13
 
10
14
  # Kakurenbo Mixin to ActiveRecord::Base.
11
15
  ActiveRecord::Base.send :include, Kakurenbo::MixinARBase
16
+
17
+ # Kakurenbo Mixin to ActiveRecord::Relation.
18
+ ActiveRecord::Relation.send :include, Kakurenbo::MixinARRelation
@@ -1,5 +1,5 @@
1
1
  module Kakurenbo
2
- module SoftDeleteCore
2
+ module Core
3
3
  # Extend ClassMethods after include.
4
4
  def self.included(base_class)
5
5
  base_class.extend ClassMethods
@@ -8,28 +8,13 @@ module Kakurenbo
8
8
  base_class.extend Aliases
9
9
  end
10
10
 
11
- module ClassMethods
12
- def paranoid?
13
- true
14
- end
15
-
16
- # Destroy model(s).
17
- #
18
- # @param id [Array<Integer> or Integer] id or ids
19
- def destroy(id)
20
- transaction do
21
- where(:id => id).each{|m| m.destroy}
22
- end
23
- end
24
-
25
- # Restore model(s).
26
- #
27
- # @param id [Array<Integer> or Integer] id or ids.
28
- # @param options [Hash] options(same restore of instance methods.)
29
- def restore(id, options = {:recursive => true})
30
- transaction do
31
- only_deleted.where(:id => id).each{|m| m.restore!(options)}
32
- end
11
+ module Aliases
12
+ def self.extended(base_class)
13
+ base_class.instance_eval {
14
+ alias_method :deleted?, :destroyed?
15
+ alias_method :recover, :restore
16
+ alias_method :recover!, :restore!
17
+ }
33
18
  end
34
19
  end
35
20
 
@@ -41,51 +26,76 @@ module Kakurenbo
41
26
  set_callback(:restore, on, *args, &block)
42
27
  end
43
28
  end
44
- base_class.define_callbacks :restore
29
+ base_class.define_model_callbacks :restore
45
30
  end
46
31
  end
47
32
 
33
+ module ClassMethods
34
+ def paranoid?; true end
35
+ end
36
+
48
37
  module Scopes
49
38
  def self.extended(base_class)
50
39
  base_class.instance_eval {
51
40
  scope :only_deleted, ->{ with_deleted.where.not( kakurenbo_column => nil ) }
52
- scope :with_deleted, ->{ all.tap{ |s| s.default_scoped = false } }
53
41
  scope :without_deleted, ->{ where(kakurenbo_column => nil) }
42
+ if ActiveRecord::VERSION::STRING >= "4.1"
43
+ scope :with_deleted, ->{ unscope :where => kakurenbo_column }
44
+ else
45
+ scope :with_deleted, ->{ all.tap{ |s| s.default_scoped = false } }
46
+ end
54
47
 
55
48
  default_scope ->{ without_deleted }
56
49
  }
57
50
  end
58
51
  end
59
52
 
60
- module Aliases
61
- def self.extended(base_class)
62
- base_class.instance_eval {
63
- alias_method :delete!, :hard_delete!
64
- alias_method :deleted?, :destroyed?
65
- alias_method :restore, :restore!
66
- alias_method :recover, :restore!
67
- }
53
+ # delete record.
54
+ #
55
+ # @param options [Hash] options.
56
+ # @option options [Boolean] hard (false) if hard-delete.
57
+ def delete(options = {:hard => false})
58
+ if options[:hard]
59
+ self.class.delete(self.id, options)
60
+ else
61
+ return if new_record? or destroyed?
62
+ update_column kakurenbo_column, current_time_from_proper_timezone
68
63
  end
69
64
  end
70
65
 
71
- def delete
72
- return if new_record? or destroyed?
73
- update_column kakurenbo_column, current_time_from_proper_timezone
66
+ # destroy record and run callbacks.
67
+ #
68
+ # @param options [Hash] options.
69
+ # @option options [Boolean] hard (false) if hard-delete.
70
+ #
71
+ # @return [Boolean, self] if action is cancelled, return false.
72
+ def destroy(options = {:hard => false})
73
+ if options[:hard]
74
+ with_transaction_returning_status do
75
+ hard_destroy_associated_records
76
+ self.reload.hard_destroy
77
+ end
78
+ else
79
+ return true if destroyed?
80
+ with_transaction_returning_status do
81
+ destroy_at = current_time_from_proper_timezone
82
+ run_callbacks(:destroy){ update_column kakurenbo_column, destroy_at; self }
83
+ end
84
+ end
74
85
  end
75
86
 
76
- def destroy
77
- return if destroyed?
78
- with_transaction_returning_status do
79
- destroy_at = current_time_from_proper_timezone
80
- run_callbacks(:destroy){ update_column kakurenbo_column, destroy_at }
81
- end
87
+ # destroy record and run callbacks.
88
+ #
89
+ # @param options [Hash] options.
90
+ # @option options [Boolean] hard (false) if hard-delete.
91
+ #
92
+ # @return [self] self.
93
+ def destroy!(options = {:hard => false})
94
+ destroy(options) || raise(ActiveRecord::RecordNotDestroyed)
82
95
  end
83
96
 
84
- def destroy!
85
- with_transaction_returning_status do
86
- hard_destroy_associated_records
87
- self.reload.hard_destroy!
88
- end
97
+ def destroy_row
98
+ relation_for_destroy.delete_all(nil, :hard => true)
89
99
  end
90
100
 
91
101
  def destroyed?
@@ -103,19 +113,32 @@ module Kakurenbo
103
113
  # restore record.
104
114
  #
105
115
  # @param options [Hash] options.
106
- # defaults: {
107
- # recursive: true
108
- # }
109
- def restore!(options = {:recursive => true})
116
+ # @option options [Boolean] recursive (true) if restore recursive.
117
+ #
118
+ # @return [Boolean, self] if action is cancelled, return false.
119
+ def restore(options = {:recursive => true})
120
+ return false unless destroyed?
121
+
110
122
  with_transaction_returning_status do
111
123
  run_callbacks(:restore) do
112
124
  parent_deleted_at = send(kakurenbo_column)
113
- update_column kakurenbo_column, nil
114
125
  restore_associated_records(parent_deleted_at) if options[:recursive]
126
+ update_column kakurenbo_column, nil
127
+ self
115
128
  end
116
129
  end
117
130
  end
118
131
 
132
+ # restore record.
133
+ #
134
+ # @param options [Hash] options.
135
+ # @option options [Boolean] hard (false) if hard-delete.
136
+ #
137
+ # @return [self] self.
138
+ def restore!(options = {:recursive => true})
139
+ restore(options) || raise(ActiveRecord::RecordNotRestored)
140
+ end
141
+
119
142
  private
120
143
  # get recoreds of association.
121
144
  #
@@ -148,7 +171,7 @@ module Kakurenbo
148
171
  # Hard-Destroy associated records.
149
172
  def hard_destroy_associated_records
150
173
  each_dependent_destroy_records do |record|
151
- record.destroy!
174
+ record.destroy(hard: true)
152
175
  end
153
176
  end
154
177
 
@@ -6,31 +6,60 @@ module Kakurenbo
6
6
  end
7
7
 
8
8
  module ClassMethods
9
+ delegate :restore, :restore_all, {:to => :with_deleted}
10
+
9
11
  # Initialize Kakurenbo in child class.
10
12
  def inherited(child_class)
13
+ super
14
+
15
+ child_class.define_singleton_method :table_name= do |value|
16
+ super(value)
17
+ if has_kakurenbo_column?
18
+ remodel_as_soft_delete
19
+ else
20
+ remodel_as_original
21
+ end
22
+ end
23
+
11
24
  child_class.instance_eval do
12
25
  remodel_as_soft_delete if has_kakurenbo_column?
13
26
  end
14
- super
27
+ end
28
+
29
+ # Remodel Model as normal.
30
+ # @note Restore to original model.
31
+ def remodel_as_original
32
+ if paranoid?
33
+ alias_method :delete, :hard_delete
34
+ alias_method :destroy, :hard_destroy
35
+ alias_method :destroy!, :hard_destroy!
36
+
37
+ singleton_class.send(:alias_method, :delete, :hard_delete)
38
+ singleton_class.send(:alias_method, :delete_all, :hard_delete_all)
39
+
40
+ define_singleton_method(:paranoid?) { false }
41
+ end
15
42
  end
16
43
 
17
44
  # Remodel Model as soft-delete.
18
45
  #
19
- # @options [Hash] option
20
- # default: {
21
- # :column => :deleted_at
22
- # }
46
+ # @params option [Hash] option.
47
+ # @option option [Symbol] column column of kakurenbo.
23
48
  def remodel_as_soft_delete(options = {})
24
49
  options.reverse_merge!(
25
50
  :column => :deleted_at
26
51
  )
27
52
 
28
53
  unless paranoid?
29
- alias_method :hard_delete!, :delete
30
- alias_method :hard_destroy!, :destroy
54
+ alias_method :hard_delete, :delete
55
+ alias_method :hard_destroy, :destroy
56
+ alias_method :hard_destroy!, :destroy!
57
+
58
+ singleton_class.send(:alias_method, :hard_delete, :delete)
59
+ singleton_class.send(:alias_method, :hard_delete_all, :delete_all)
31
60
 
32
61
  class_attribute :kakurenbo_column
33
- include Kakurenbo::SoftDeleteCore
62
+ include Kakurenbo::Core
34
63
  end
35
64
 
36
65
  self.kakurenbo_column = options[:column]
@@ -42,19 +71,13 @@ module Kakurenbo
42
71
  false
43
72
  end
44
73
 
45
- # When set table name, remodel.
46
- def table_name=(value)
47
- super
48
- remodel_as_soft_delete if has_kakurenbo_column?
49
- end
50
-
51
74
  private
52
75
  # Check if Model has kakurenbo_column.
53
76
  #
54
77
  # @return [Boolean] result.
55
78
  def has_kakurenbo_column?
56
79
  begin
57
- column_names.include?('deleted_at')
80
+ table_exists? and column_names.include?('deleted_at')
58
81
  rescue
59
82
  false
60
83
  end
@@ -0,0 +1,82 @@
1
+ module Kakurenbo
2
+ module MixinARRelation
3
+ # Extend ClassMethods after include.
4
+ def self.included(base_class)
5
+ base_class.class_eval do
6
+ alias_method :hard_delete_all, :delete_all
7
+
8
+ # delete selected id or ids.
9
+ #
10
+ # @param id [Integer, Array<Integer>] ID or IDs.
11
+ # @param options [Hash] options.
12
+ # @option options [Boolean] hard (false) if hard-delete.
13
+ def delete(id, options = {:hard => false})
14
+ delete_all({:id => id}, options)
15
+ end
16
+
17
+ # delete all record.
18
+ #
19
+ # @param conditions [Object] conditions.
20
+ # @param options [Hash] options.
21
+ # @option options [Boolean] hard (false) if hard-delete.
22
+ def delete_all(conditions = nil, options = {:hard => false})
23
+ return hard_delete_all(conditions) unless klass.paranoid?
24
+
25
+ if conditions
26
+ where(conditions).delete_all(nil, options)
27
+ else
28
+ if options[:hard]
29
+ hard_delete_all
30
+ else
31
+ update_all({ klass.kakurenbo_column => Time.now })
32
+ end
33
+ end
34
+ end
35
+
36
+ # destroy selected id or ids.
37
+ #
38
+ # @param id [Integer, Array<Integer>] ID or IDs.
39
+ # @param options [Hash] options.
40
+ # @option options [Boolean] hard (false) if hard-delete.
41
+ def destroy(id, options = {:hard => false})
42
+ destroy_all({:id => id}, options)
43
+ end
44
+
45
+ # destroy all record.
46
+ #
47
+ # @param conditions [Object] conditions.
48
+ # @param options [Hash] options.
49
+ # @option options [Boolean] hard (false) if hard-delete.
50
+ def destroy_all(conditions = nil, options = {:hard => false})
51
+ if conditions
52
+ where(conditions).destroy_all(nil, options)
53
+ else
54
+ to_a.each {|object| object.destroy(options) }.tap { reset }
55
+ end
56
+ end
57
+
58
+ # restore selected id or ids.
59
+ #
60
+ # @param id [Integer, Array<Integer>] ID or IDs.
61
+ # @param options [Hash] options.
62
+ # @option options [Boolean] recursive (true) if restore recursive.
63
+ def restore(id, options = {:recursive => true})
64
+ restore_all({:id => id}, options)
65
+ end
66
+
67
+ # restore all record.
68
+ #
69
+ # @param conditions [Object] conditions.
70
+ # @param options [Hash] options.
71
+ # @option options [Boolean] recursive (true) if restore recursive.
72
+ def restore_all(conditions = nil, options = {:recursive => true})
73
+ if conditions
74
+ where(conditions).restore_all(nil, options)
75
+ else
76
+ to_a.each {|object| object.restore(options) }.tap { reset }
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end