rollbacker 1.0.0 → 1.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/README.md +111 -6
- data/lib/rollbacker/base.rb +1 -1
- data/lib/rollbacker/database_rollback.rb +1 -1
- data/lib/rollbacker/rollbacker_change.rb +54 -1
- data/lib/rollbacker/version.rb +1 -1
- data/spec/database_rollback_spec.rb +4 -4
- data/spec/rollbacker_change_spec.rb +279 -0
- metadata +2 -1
data/README.md
CHANGED
|
@@ -1,16 +1,121 @@
|
|
|
1
|
-
|
|
1
|
+
Rollbacker
|
|
2
|
+
==========
|
|
2
3
|
|
|
3
|
-
Rollbacker is a manage tool for auditing changes to your ActiveRecord.
|
|
4
|
+
**Rollbacker** is a manage tool for auditing changes to your ActiveRecord.
|
|
4
5
|
The changes of objects are added to a queue where the auditor can approve and reject those changes.
|
|
5
6
|
|
|
6
|
-
## Installation
|
|
7
|
+
## Installation
|
|
7
8
|
|
|
8
9
|
To use it with your Rails 3 project, add the following line to your Gemfile
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
```ruby
|
|
12
|
+
gem 'rollbacker'
|
|
13
|
+
```
|
|
11
14
|
|
|
12
15
|
Generate the migration and create the rollbacker_changes table
|
|
16
|
+
```bash
|
|
17
|
+
$ rails generate rollbacker:migration
|
|
18
|
+
$ rake db:migrate
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
Simply call `rollbacker` on your models:
|
|
24
|
+
|
|
25
|
+
```ruby
|
|
26
|
+
class Model < ActiveRecord::Base
|
|
27
|
+
rollbacker(:create, :update, :destroy)
|
|
28
|
+
end
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
After that, whenever a model is created, updated or destroyed, a new RollbackerChange record is created.
|
|
32
|
+
|
|
33
|
+
```ruby
|
|
34
|
+
# Create Model
|
|
35
|
+
> Model.count
|
|
36
|
+
=> 0
|
|
37
|
+
> Model.create(name: 'Name', value: 'Value')
|
|
38
|
+
=> #<Model id: nil, name: "Name", value: "Value">
|
|
39
|
+
> Model.count
|
|
40
|
+
=> 0
|
|
41
|
+
> RollbackerChange.last.approve
|
|
42
|
+
> Model.count
|
|
43
|
+
=> 1
|
|
44
|
+
|
|
45
|
+
# Update Model
|
|
46
|
+
> m = Model.first
|
|
47
|
+
=> #<Model id: 1, name: "Name", value: "Value">
|
|
48
|
+
> m.update_attribute(:name, 'New')
|
|
49
|
+
> m.reload
|
|
50
|
+
=> #<Model id: 1, name: "Name", value: "Value">
|
|
51
|
+
> m.rollbacker_changes.last.rollbacked_changes
|
|
52
|
+
=> {"name"=>["Name", "New"]}
|
|
53
|
+
> m.update_attributes(:name=>'Newer', :value => 'New')
|
|
54
|
+
> m.rollbacker_changes.last.rollbacked_changes
|
|
55
|
+
=> {"name"=>["Name", "Newer"], "value"=>["Value", "New"]}
|
|
56
|
+
> m.rollbacker_changes.last.approve('value')
|
|
57
|
+
> m.reload
|
|
58
|
+
=> #<Model id: 1, name: "Name", value: "New">
|
|
59
|
+
> m.rollbacker_changes.last.rollbacked_changes
|
|
60
|
+
=> {"name"=>["Name", "Newer"]}
|
|
61
|
+
> m.rollbacker_changes.last.reject
|
|
62
|
+
> m.reload
|
|
63
|
+
=> #<Model id: 1, name: "Name", value: "New">
|
|
64
|
+
|
|
65
|
+
# Destroy Model
|
|
66
|
+
> m.destroy
|
|
67
|
+
> Model.count
|
|
68
|
+
=> 1
|
|
69
|
+
> m.rollbacker_changes.last.approve
|
|
70
|
+
> Model.count
|
|
71
|
+
=> 0
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
The rollbacked_changes column automatically serializes the changes of any model attributes modified during the action. If there are only a few attributes you want to track or a couple that you want to prevent from being tracked, you can specify that in the rollbacker call. For example
|
|
75
|
+
```ruby
|
|
76
|
+
rollbacker(:create, :destroy, :except => [:title])
|
|
77
|
+
rollbacker(:update, :only => :title)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Current User Tracking
|
|
81
|
+
|
|
82
|
+
If you're using Rollbacker in a Rails application, all changes made within a request will automatically be attributed to the current user. By default, Rollbacker uses the `current_user` method in your controller.
|
|
83
|
+
|
|
84
|
+
```ruby
|
|
85
|
+
class PostsController < ApplicationController
|
|
86
|
+
def create
|
|
87
|
+
current_user # => #<User name: "Steve">
|
|
88
|
+
@post = Post.create(params[:post])
|
|
89
|
+
@post.rollbacker_changes.last.user # => #<User name: "Steve">
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Integration
|
|
95
|
+
There may be some instances where you need to perform an action on your model object without Rollbacker. In those cases you can include the Rollbacker::Status module for help.
|
|
96
|
+
```ruby
|
|
97
|
+
class PostsController < ApplicationController
|
|
98
|
+
include Rollbacker::Status
|
|
99
|
+
|
|
100
|
+
def update
|
|
101
|
+
post = Post.find(params[:id])
|
|
102
|
+
without_rollbacker { post.update_attributes(params[:post]) } # Rollbacker is disabled for the entire block
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
You can also force Rollbacker to track any actions within a block as a specified user.
|
|
108
|
+
```ruby
|
|
109
|
+
class PostsController < ApplicationController
|
|
110
|
+
include Rollbacker::Status
|
|
111
|
+
|
|
112
|
+
def update
|
|
113
|
+
post = Post.find(params[:id])
|
|
114
|
+
rollbacker_as(another_user) { post.update_attributes(params[:post]) }
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
For more details, I suggest you check out the test examples in the spec folder itself.
|
|
13
120
|
|
|
14
|
-
rails generate rollbacker:migration
|
|
15
|
-
rake db:migrate
|
|
16
121
|
|
data/lib/rollbacker/base.rb
CHANGED
|
@@ -23,7 +23,7 @@ module Rollbacker
|
|
|
23
23
|
|
|
24
24
|
config = Rollbacker::Config.new(*args)
|
|
25
25
|
config.actions.each do |action|
|
|
26
|
-
send "
|
|
26
|
+
send "before_#{action}", Rollbacker::DatabaseRollback.new(config.options)
|
|
27
27
|
# send :after_rollback, Rollbacker::Recorder.new(action, config.options, &blk), :on => action
|
|
28
28
|
end
|
|
29
29
|
send :after_rollback, Rollbacker::Recorder.new(config.options, &blk)
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
require 'active_record'
|
|
2
2
|
require 'rollbacker/config'
|
|
3
|
+
require 'rollbacker/status'
|
|
3
4
|
|
|
4
5
|
class RollbackerChange < ActiveRecord::Base
|
|
6
|
+
include Rollbacker::Status
|
|
5
7
|
belongs_to :rollbackable, :polymorphic => true
|
|
6
8
|
belongs_to :user, :polymorphic => true
|
|
7
9
|
|
|
@@ -9,14 +11,65 @@ class RollbackerChange < ActiveRecord::Base
|
|
|
9
11
|
|
|
10
12
|
serialize :rollbacked_changes
|
|
11
13
|
|
|
12
|
-
def new_attributes
|
|
14
|
+
def new_attributes(*fields)
|
|
13
15
|
(rollbacked_changes || {}).inject({}.with_indifferent_access) do |attrs,(attr,values)|
|
|
14
16
|
attrs[attr] = values.is_a?(Array) ? values.last : values
|
|
15
17
|
attrs
|
|
18
|
+
end.select do |k,v|
|
|
19
|
+
fields.blank? ? true : fields.map(&:to_s).include?(k)
|
|
16
20
|
end
|
|
17
21
|
end
|
|
18
22
|
|
|
23
|
+
|
|
24
|
+
def reject(*fields)
|
|
25
|
+
without_rollbacker do
|
|
26
|
+
case self.action.to_s
|
|
27
|
+
when 'update', 'create'
|
|
28
|
+
update_changes_after_approve_or_reject(*fields)
|
|
29
|
+
when 'destroy'
|
|
30
|
+
self.rollbacked_changes = nil
|
|
31
|
+
self.destroy
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def approve(*fields)
|
|
37
|
+
without_rollbacker do
|
|
38
|
+
edits = self.new_attributes(*fields)
|
|
39
|
+
case self.action.to_s
|
|
40
|
+
when 'update'
|
|
41
|
+
if edits.present? && self.rollbackable && self.rollbackable.update_attributes(edits)
|
|
42
|
+
update_changes_after_approve_or_reject(*fields)
|
|
43
|
+
return true
|
|
44
|
+
end
|
|
45
|
+
when 'create'
|
|
46
|
+
if edits.present? && self.rollbackable_type.constantize.create(edits)
|
|
47
|
+
self.rollbacked_changes = nil
|
|
48
|
+
self.destroy
|
|
49
|
+
end
|
|
50
|
+
when 'destroy'
|
|
51
|
+
if self.rollbackable && self.rollbackable.destroy
|
|
52
|
+
self.rollbacked_changes = nil
|
|
53
|
+
self.destroy
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def create_action?; self[:action].to_s == 'create' end
|
|
60
|
+
def update_action?; self[:action].to_s == 'update' end
|
|
61
|
+
def destroy_action?; self[:action].to_s == 'destroy' end
|
|
62
|
+
|
|
19
63
|
private
|
|
64
|
+
def update_changes_after_approve_or_reject(*fields)
|
|
65
|
+
edits = fields.blank? ? nil : rollbacked_changes.delete_if{|k,v| fields.map(&:to_s).include?(k) }
|
|
66
|
+
if edits.present?
|
|
67
|
+
self.update_attribute(:rollbacked_changes, edits)
|
|
68
|
+
else
|
|
69
|
+
self.rollbacked_changes = nil
|
|
70
|
+
self.destroy
|
|
71
|
+
end
|
|
72
|
+
end
|
|
20
73
|
|
|
21
74
|
def set_user
|
|
22
75
|
self.user = Rollbacker::User.current_user if self.user_id.nil?
|
data/lib/rollbacker/version.rb
CHANGED
|
@@ -11,11 +11,11 @@ describe Rollbacker::DatabaseRollback do
|
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
[:create, :update, :destroy].each do |action|
|
|
14
|
-
it "should respond with
|
|
14
|
+
it "should respond with before_#{action}" do
|
|
15
15
|
model = Model.new(name: 'name')
|
|
16
16
|
config = Rollbacker::Config.new(action)
|
|
17
17
|
callback = Rollbacker::DatabaseRollback.new(config.options)
|
|
18
|
-
callback.should respond_to("
|
|
18
|
+
callback.should respond_to("before_#{action}")
|
|
19
19
|
end
|
|
20
20
|
end
|
|
21
21
|
|
|
@@ -27,7 +27,7 @@ describe Rollbacker::DatabaseRollback do
|
|
|
27
27
|
|
|
28
28
|
lambda {
|
|
29
29
|
without_rollbacker do
|
|
30
|
-
callback.send :
|
|
30
|
+
callback.send :before_create, model
|
|
31
31
|
end
|
|
32
32
|
}.should_not raise_exception(ActiveRecord::Rollback)
|
|
33
33
|
end
|
|
@@ -39,7 +39,7 @@ describe Rollbacker::DatabaseRollback do
|
|
|
39
39
|
callback = Rollbacker::DatabaseRollback.new(config.options)
|
|
40
40
|
|
|
41
41
|
lambda {
|
|
42
|
-
callback.send :
|
|
42
|
+
callback.send :before_create, model
|
|
43
43
|
}.should raise_exception(ActiveRecord::Rollback)
|
|
44
44
|
end
|
|
45
45
|
end
|
|
@@ -15,5 +15,284 @@ describe RollbackerChange do
|
|
|
15
15
|
record = RollbackerChange.create(:rollbackable => @rollbackable, :user => @user, :action => :create)
|
|
16
16
|
record.user.should == @user
|
|
17
17
|
end
|
|
18
|
+
|
|
19
|
+
describe '#new_attributes' do
|
|
20
|
+
it "should collect all new values" do
|
|
21
|
+
record = RollbackerChange.new(rollbacked_changes: {'name'=>[nil, 'Name'], 'value'=>[nil, 'Value']})
|
|
22
|
+
record.new_attributes.should == {'name'=>'Name','value'=>'Value'}
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "should select only specific attributes" do
|
|
26
|
+
record = RollbackerChange.new(rollbacked_changes: {'name'=>[nil, 'Name'], 'value'=>[nil, 'Value']})
|
|
27
|
+
record.new_attributes('name').should == {'name'=>'Name'}
|
|
28
|
+
record.new_attributes(:name).should == {'name'=>'Name'}
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
describe '#update_changes_after_approve_or_reject' do
|
|
33
|
+
it "should remove edits from rollbacked_changes field" do
|
|
34
|
+
record = RollbackerChange.new(rollbacked_changes: {'name'=>[nil, 'Name'], 'value'=>[nil, 'Value']})
|
|
35
|
+
record.send(:update_changes_after_approve_or_reject, 'name')
|
|
36
|
+
record.rollbacked_changes.should == {'value'=>[nil, 'Value']}
|
|
37
|
+
record.should_not be_destroyed
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "should be able update multiple fields" do
|
|
41
|
+
record = RollbackerChange.new(rollbacked_changes: {'name'=>[nil, 'Name'], 'value'=>[nil, 'Value']})
|
|
42
|
+
record.send(:update_changes_after_approve_or_reject, 'name', 'value')
|
|
43
|
+
record.rollbacked_changes.should be_nil
|
|
44
|
+
record.should be_destroyed
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "should destroy record and remove all changes with no arguments" do
|
|
48
|
+
record = RollbackerChange.new(rollbacked_changes: {'name'=>[nil, 'Name'], 'value'=>[nil, 'Value']})
|
|
49
|
+
record.send(:update_changes_after_approve_or_reject)
|
|
50
|
+
record.rollbacked_changes.should be_nil
|
|
51
|
+
record.should be_destroyed
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "should destroy record if no more changes" do
|
|
55
|
+
record = RollbackerChange.create(rollbacked_changes: {'name'=>[nil, 'Name']})
|
|
56
|
+
record.send(:update_changes_after_approve_or_reject, 'name')
|
|
57
|
+
record.rollbacked_changes.should be_nil
|
|
58
|
+
record.should be_destroyed
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it "should destroy record if no more changes" do
|
|
62
|
+
record = RollbackerChange.create(rollbacked_changes: {'name'=>[nil, 'Name']})
|
|
63
|
+
record.send(:update_changes_after_approve_or_reject, :name)
|
|
64
|
+
record.rollbacked_changes.should be_nil
|
|
65
|
+
record.should be_destroyed
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
describe "reject" do
|
|
70
|
+
context "on :update" do
|
|
71
|
+
let(:action) { :update }
|
|
72
|
+
it "should not change anything with a has no change about the field" do
|
|
73
|
+
record = RollbackerChange.create({
|
|
74
|
+
:rollbacked_changes => {'name'=>[nil, 'Name']},
|
|
75
|
+
:rollbackable => @rollbackable,
|
|
76
|
+
:user => @user,
|
|
77
|
+
:action => action
|
|
78
|
+
})
|
|
79
|
+
record.rollbackable.should be_present
|
|
80
|
+
record.should be_update_action
|
|
81
|
+
lambda {
|
|
82
|
+
record.reject('value').should be_true
|
|
83
|
+
}.should_not change(RollbackerChange, :count)
|
|
84
|
+
record.reload.rollbacked_changes.should == {'name'=>[nil, 'Name']}
|
|
85
|
+
end
|
|
86
|
+
it "should NOT apply the change to the auditable model" do
|
|
87
|
+
record = RollbackerChange.create({
|
|
88
|
+
:rollbacked_changes => {'name'=>[nil, 'Name'], 'value'=>[nil, 'Value']},
|
|
89
|
+
:rollbackable => @rollbackable,
|
|
90
|
+
:user => @user,
|
|
91
|
+
:action => action
|
|
92
|
+
})
|
|
93
|
+
record.rollbackable.should be_present
|
|
94
|
+
record.should be_update_action
|
|
95
|
+
lambda {
|
|
96
|
+
record.reject('name').should be_true
|
|
97
|
+
}.should_not change(RollbackerChange, :count)
|
|
98
|
+
@rollbackable.reload.name.should be_nil
|
|
99
|
+
record.rollbacked_changes.should == {'value'=>[nil, 'Value']}
|
|
100
|
+
record.should_not be_destroyed
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
context "on :create" do
|
|
105
|
+
let(:action) { :create }
|
|
106
|
+
it "should NOT be created if has no change about the field" do
|
|
107
|
+
record = RollbackerChange.create({
|
|
108
|
+
:rollbacked_changes => {'name'=>[nil, 'Name']},
|
|
109
|
+
:rollbackable_type => 'Model',
|
|
110
|
+
:user => @user,
|
|
111
|
+
:action => action
|
|
112
|
+
})
|
|
113
|
+
record.should be_create_action
|
|
114
|
+
lambda {
|
|
115
|
+
lambda {
|
|
116
|
+
record.reject('value').should be_true
|
|
117
|
+
}.should_not change(RollbackerChange, :count)
|
|
118
|
+
}.should_not change(Model, :count)
|
|
119
|
+
record.reload.rollbacked_changes.should == {'name'=>[nil, 'Name']}
|
|
120
|
+
end
|
|
121
|
+
it "should be able to only update changes without insert a new record" do
|
|
122
|
+
record = RollbackerChange.create({
|
|
123
|
+
:rollbacked_changes => {'name'=>[nil, 'Name'], 'value'=>[nil, 'Value']},
|
|
124
|
+
:rollbackable_type => 'Model',
|
|
125
|
+
:user => @user,
|
|
126
|
+
:action => action
|
|
127
|
+
})
|
|
128
|
+
record.should be_create_action
|
|
129
|
+
lambda {
|
|
130
|
+
lambda {
|
|
131
|
+
record.reject('value').should be_true
|
|
132
|
+
}.should_not change(RollbackerChange, :count)
|
|
133
|
+
}.should_not change(Model, :count)
|
|
134
|
+
record.reload.rollbacked_changes.should == {'name'=>[nil, 'Name']}
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
context "on :destroy" do
|
|
138
|
+
let(:action) { :destroy }
|
|
139
|
+
it "should only remove rollbacker_change record and discart rollbacked_changes" do
|
|
140
|
+
record = RollbackerChange.create({
|
|
141
|
+
:rollbacked_changes => {'name'=>[nil, 'Name'], 'value'=>[nil, 'Value']},
|
|
142
|
+
:rollbackable => @rollbackable,
|
|
143
|
+
:user => @user,
|
|
144
|
+
:action => action
|
|
145
|
+
})
|
|
146
|
+
record.rollbackable.should be_present
|
|
147
|
+
record.should be_destroy_action
|
|
148
|
+
lambda {
|
|
149
|
+
lambda {
|
|
150
|
+
record.reject.should be_true
|
|
151
|
+
}.should change(RollbackerChange, :count).by(-1)
|
|
152
|
+
}.should_not change(Model, :count)
|
|
153
|
+
@rollbackable.reload.name.should be_nil
|
|
154
|
+
@rollbackable.reload.value.should be_nil
|
|
155
|
+
record.rollbacked_changes.should be_nil
|
|
156
|
+
record.should be_destroyed
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
describe "approve" do
|
|
162
|
+
context "on :update" do
|
|
163
|
+
let(:action) { :update}
|
|
164
|
+
it "should not change anything with a has no change about the field" do
|
|
165
|
+
record = RollbackerChange.create({
|
|
166
|
+
:rollbacked_changes => {'name'=>[nil, 'Name']},
|
|
167
|
+
:rollbackable => @rollbackable,
|
|
168
|
+
:user => @user,
|
|
169
|
+
:action => action
|
|
170
|
+
})
|
|
171
|
+
record.rollbackable.should be_present
|
|
172
|
+
record.should be_update_action
|
|
173
|
+
lambda {
|
|
174
|
+
lambda {
|
|
175
|
+
record.approve('value').should be_nil
|
|
176
|
+
}.should_not change(RollbackerChange, :count)
|
|
177
|
+
}.should_not change(Model, :count)
|
|
178
|
+
record.reload.rollbacked_changes.should == {'name'=>[nil, 'Name']}
|
|
179
|
+
end
|
|
180
|
+
it "should apply the change to the auditable model from a specific field" do
|
|
181
|
+
record = RollbackerChange.create({
|
|
182
|
+
:rollbacked_changes => {'name'=>[nil, 'Name'], 'value'=>[nil, 'Value']},
|
|
183
|
+
:rollbackable => @rollbackable,
|
|
184
|
+
:user => @user,
|
|
185
|
+
:action => action
|
|
186
|
+
})
|
|
187
|
+
record.rollbackable.should be_present
|
|
188
|
+
record.should be_update_action
|
|
189
|
+
lambda {
|
|
190
|
+
lambda {
|
|
191
|
+
record.approve('name').should be_true
|
|
192
|
+
}.should_not change(RollbackerChange, :count)
|
|
193
|
+
}.should_not change(Model, :count)
|
|
194
|
+
@rollbackable.reload.name.should == 'Name'
|
|
195
|
+
record.reload.rollbacked_changes.should == {'value'=>[nil, 'Value']}
|
|
196
|
+
record.should_not be_destroyed
|
|
197
|
+
end
|
|
198
|
+
it "should apply all changes to the auditable model" do
|
|
199
|
+
record = RollbackerChange.create({
|
|
200
|
+
:rollbacked_changes => {'name'=>[nil, 'Name'], 'value'=>[nil, 'Value']},
|
|
201
|
+
:rollbackable => @rollbackable,
|
|
202
|
+
:user => @user,
|
|
203
|
+
:action => action
|
|
204
|
+
})
|
|
205
|
+
record.rollbackable.should be_present
|
|
206
|
+
record.should be_update_action
|
|
207
|
+
lambda {
|
|
208
|
+
lambda {
|
|
209
|
+
record.approve.should be_true
|
|
210
|
+
}.should change(RollbackerChange, :count).by(-1)
|
|
211
|
+
}.should_not change(Model, :count)
|
|
212
|
+
@rollbackable.reload.name.should == 'Name'
|
|
213
|
+
@rollbackable.reload.value.should == 'Value'
|
|
214
|
+
record.rollbacked_changes.should be_nil
|
|
215
|
+
record.should be_destroyed
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
context "on :create" do
|
|
220
|
+
let(:action) { :create }
|
|
221
|
+
it "should not change anything with a has no change about the field" do
|
|
222
|
+
record = RollbackerChange.create({
|
|
223
|
+
:rollbacked_changes => {'name'=>[nil, 'Name']},
|
|
224
|
+
:rollbackable_type => 'Model',
|
|
225
|
+
:user => @user,
|
|
226
|
+
:action => action
|
|
227
|
+
})
|
|
228
|
+
record.should be_create_action
|
|
229
|
+
lambda {
|
|
230
|
+
lambda {
|
|
231
|
+
record.approve('value').should be_nil
|
|
232
|
+
}.should_not change(RollbackerChange, :count)
|
|
233
|
+
}.should_not change(Model, :count)
|
|
234
|
+
record.reload.rollbacked_changes.should == {'name'=>[nil, 'Name']}
|
|
235
|
+
end
|
|
236
|
+
it "should be created a rollbackable model from specific fields" do
|
|
237
|
+
record = RollbackerChange.create({
|
|
238
|
+
:rollbacked_changes => {'name'=>[nil, 'Newer Name'], 'value'=>[nil,'Newer Value']},
|
|
239
|
+
:rollbackable_type => 'Model',
|
|
240
|
+
:user => @user,
|
|
241
|
+
:action => action
|
|
242
|
+
})
|
|
243
|
+
record.should be_create_action
|
|
244
|
+
lambda {
|
|
245
|
+
lambda {
|
|
246
|
+
record.approve('name').should be_true
|
|
247
|
+
}.should change(RollbackerChange, :count).by(-1)
|
|
248
|
+
}.should change(Model, :count).by(1)
|
|
249
|
+
record.rollbacked_changes.should be_nil
|
|
250
|
+
record.should be_destroyed
|
|
251
|
+
rollbackable = Model.last
|
|
252
|
+
rollbackable.name.should == 'Newer Name'
|
|
253
|
+
rollbackable.value.should be_nil
|
|
254
|
+
end
|
|
255
|
+
it "should be created a rollbackable model with all fields" do
|
|
256
|
+
record = RollbackerChange.create({
|
|
257
|
+
:rollbacked_changes => {'name'=>[nil, 'Name'], 'value'=>[nil,'Value']},
|
|
258
|
+
:rollbackable_type => 'Model',
|
|
259
|
+
:user => @user,
|
|
260
|
+
:action => action
|
|
261
|
+
})
|
|
262
|
+
record.should be_create_action
|
|
263
|
+
lambda {
|
|
264
|
+
lambda {
|
|
265
|
+
record.approve.should be_true
|
|
266
|
+
}.should change(RollbackerChange, :count).by(-1)
|
|
267
|
+
}.should change(Model, :count).by(1)
|
|
268
|
+
record.rollbacked_changes.should be_nil
|
|
269
|
+
record.should be_destroyed
|
|
270
|
+
rollbackable = Model.last
|
|
271
|
+
rollbackable.name.should == 'Name'
|
|
272
|
+
rollbackable.value.should == 'Value'
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
context "on :destroy" do
|
|
276
|
+
let(:action) { :destroy }
|
|
277
|
+
it "should not change anything with a has no change about the field" do
|
|
278
|
+
record = RollbackerChange.create({
|
|
279
|
+
:rollbacked_changes => nil,
|
|
280
|
+
:rollbackable => @rollbackable,
|
|
281
|
+
:user => @user,
|
|
282
|
+
:action => action
|
|
283
|
+
})
|
|
284
|
+
record.rollbackable.should be_present
|
|
285
|
+
record.should be_destroy_action
|
|
286
|
+
lambda {
|
|
287
|
+
lambda {
|
|
288
|
+
record.approve.should be_true
|
|
289
|
+
}.should change(RollbackerChange, :count).by(-1)
|
|
290
|
+
}.should change(Model, :count).by(-1)
|
|
291
|
+
record.rollbacked_changes.should == nil
|
|
292
|
+
record.should be_destroyed
|
|
293
|
+
@rollbackable.should be_destroyed
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
end
|
|
18
297
|
end
|
|
19
298
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rollbacker
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.1
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -140,3 +140,4 @@ test_files:
|
|
|
140
140
|
- spec/support/model_setup.rb
|
|
141
141
|
- spec/support/transactional_specs.rb
|
|
142
142
|
- spec/user_spec.rb
|
|
143
|
+
has_rdoc:
|