kakurenbo 0.1.3 → 0.2.0

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.
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