purgatory 6.0.3 → 6.1.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
  SHA256:
3
- metadata.gz: 2af3c60d4f7b1c69ed124e020216752e1078b24eafeea8af633ec91ab25c1a14
4
- data.tar.gz: f731d8381bc1430a47999a0dfbef2acba055620c0410cebd92a1585495a027d6
3
+ metadata.gz: bab67dfd79b8b77fbb64611e198b1790b83d836b6066e9aba0d689f7580b2e74
4
+ data.tar.gz: 824ce4ac4ac15b91a46ff5c3a9a7e7e3261f7214f8f9b2514c2e33448ec6d08b
5
5
  SHA512:
6
- metadata.gz: 7e42df9ba9269376d816c414c4dce1f7f115ab66598d2bf98965d4d8c53098f636819def2be40cc394cbe7a4efd995746206a3256f21e6c4ac40e9d0840143a1
7
- data.tar.gz: c6b61df8ad74d59bc3d86e2e8d64634f406edaa81c7c91d809316f45096361f101400f4518aded25fae3b5a220d015a683a2b77ad8aa288bad7dfeece02b2dfb
6
+ metadata.gz: 45f9078948e5c4aed80c6faa396aaf5966bffd59e0842d75b206d0d1541c9464e119602178c5100bdc971f594571488823eec135736f001bd62403c84b3cde2e
7
+ data.tar.gz: 973ce5cff553f34aec2fd6f87d893ea69664ca9e0d44359af83128feea27faa642e5d6477ac235cdc179a6f65c7af68b440d3e76aef2dc6190efb064c5f13ddf
data/Gemfile CHANGED
@@ -4,7 +4,7 @@ source "http://rubygems.org"
4
4
  # gem "activesupport", ">= 2.3.5"
5
5
 
6
6
  group :test do
7
- gem "activerecord", "~> 4.1"
7
+ gem "activerecord"
8
8
  gem "rspec"
9
9
  gem "sqlite3"
10
10
  gem "pry"
data/VERSION CHANGED
@@ -1 +1 @@
1
- 6.0.3
1
+ 6.1.0
@@ -9,7 +9,7 @@ class PurgatoryGenerator < Rails::Generators::Base
9
9
  end
10
10
 
11
11
  def self.next_migration_number(dirname)
12
- if ActiveRecord::Base.timestamped_migrations
12
+ if ActiveRecord.timestamped_migrations
13
13
  Time.new.utc.strftime("%Y%m%d%H%M%S")
14
14
  else
15
15
  "%.3d" % (current_migration_number(dirname) + 1)
@@ -19,11 +19,15 @@ class PurgatoryGenerator < Rails::Generators::Base
19
19
  def create_migration_file
20
20
  ['create_purgatories', 'add_performable_method_to_purgatories'].each do |filename|
21
21
  unless self.class.migration_exists?("db/migrate", "#{filename}").present?
22
- migration_template "#{filename}.rb", "db/migrate/#{filename}.rb"
22
+ migration_template "#{filename}.rb.erb", "db/migrate/#{filename}.rb"
23
23
  end
24
24
  end
25
25
  end
26
26
 
27
+ def migration_version
28
+ format("[%d.%d]", ActiveRecord::VERSION::MAJOR, ActiveRecord::VERSION::MINOR)
29
+ end
30
+
27
31
  def create_initializer_file
28
32
  create_file 'config/initializers/purgatory.rb', <<-eos
29
33
  PurgatoryModule.configure do |config|
@@ -33,4 +37,4 @@ end
33
37
  require 'purgatory/purgatory'
34
38
  eos
35
39
  end
36
- end
40
+ end
@@ -1,4 +1,4 @@
1
- class AddPerformableMethodToPurgatories < ActiveRecord::Migration
1
+ class AddPerformableMethodToPurgatories < ActiveRecord::Migration<%= migration_version %>
2
2
  def change
3
3
  add_column :purgatories, :performable_method, :text
4
4
  end
@@ -1,4 +1,4 @@
1
- class CreatePurgatories < ActiveRecord::Migration
1
+ class CreatePurgatories < ActiveRecord::Migration<%= migration_version %>
2
2
  def change
3
3
  create_table :purgatories do |t|
4
4
  t.integer :soul_id
@@ -34,7 +34,12 @@ class Purgatory < ActiveRecord::Base
34
34
  end
35
35
 
36
36
  def sti_class
37
- requested_changes['type'].try(:last)
37
+ read_attribute(:requested_changes)['type'].try(:last)
38
+ end
39
+
40
+ # Deserialize encrypted attributes on read
41
+ def requested_changes
42
+ alter(super, :deserialize)
38
43
  end
39
44
 
40
45
  def soul_with_changes
@@ -74,7 +79,20 @@ class Purgatory < ActiveRecord::Base
74
79
  private
75
80
 
76
81
  def store_changes
77
- self.requested_changes = soul.changes
82
+ # Store the ciphertext of encrypted attributes
83
+ self.requested_changes = alter(soul.changes, :serialize)
84
+ end
85
+
86
+ def alter(changes, serialization_method)
87
+ encrypted_attr_changes = changes.slice(*soul.class.encrypted_attributes)
88
+ return changes if encrypted_attr_changes.empty?
89
+
90
+ altered = encrypted_attr_changes.each_with_object({}) do |(attribute_name, attr_changes), hsh|
91
+ type = soul.class.type_for_attribute(attribute_name)
92
+ hsh[attribute_name] = attr_changes.map { |value| type.send(serialization_method, value) }
93
+ end
94
+
95
+ changes.merge(altered)
78
96
  end
79
97
 
80
98
  def destroy_pending_with_same_soul
data/purgatory.gemspec CHANGED
@@ -1,9 +1,9 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: purgatory 6.0.1 ruby lib
2
+ # stub: purgatory 6.1.0 ruby lib
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "purgatory"
6
- s.version = "6.0.3"
6
+ s.version = "6.1.0"
7
7
 
8
8
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
9
9
  s.require_paths = ["lib"]
@@ -18,16 +18,14 @@ Gem::Specification.new do |s|
18
18
  s.files = [
19
19
  ".document",
20
20
  ".rspec",
21
- ".travis.yml",
22
21
  "Gemfile",
23
- "Gemfile.lock",
24
22
  "LICENSE.txt",
25
23
  "README.markdown",
26
24
  "VERSION",
27
25
  "init.rb",
28
26
  "lib/generators/purgatory/purgatory_generator.rb",
29
- "lib/generators/purgatory/templates/add_performable_method_to_purgatories.rb",
30
- "lib/generators/purgatory/templates/create_purgatories.rb",
27
+ "lib/generators/purgatory/templates/add_performable_method_to_purgatories.rb.erb",
28
+ "lib/generators/purgatory/templates/create_purgatories.rb.erb",
31
29
  "lib/purgatory.rb",
32
30
  "lib/purgatory/active_record_descendant_attribute_accessors.rb",
33
31
  "lib/purgatory/attribute_accessor_fields.rb",
@@ -14,37 +14,48 @@ describe Purgatory do
14
14
  before {create_object_change_purgatory}
15
15
 
16
16
  it "should create and return pending Purgatory object" do
17
- @purgatory.should be_present
18
- @purgatory.should_not be_approved
19
- @purgatory.should be_pending
20
- Purgatory.pending.count.should == 1
21
- Purgatory.pending.first.should == @purgatory
22
- Purgatory.approved.count.should be_zero
17
+ expect(@purgatory).to be_present
18
+ expect(@purgatory).not_to be_approved
19
+ expect(@purgatory).to be_pending
20
+ expect(Purgatory.pending.count).to eq(1)
21
+ expect(Purgatory.pending.first).to eq(@purgatory)
22
+ expect(Purgatory.approved.count).to be_zero
23
23
  end
24
24
 
25
25
  it "should store the soul, requester and requested changes" do
26
- @purgatory.soul.should == @widget
27
- @purgatory.requester.should == user1
28
- @purgatory.requested_changes['name'].first.should == 'foo'
29
- @purgatory.requested_changes['name'].last.should == 'bar'
30
- @purgatory.requested_changes['price'].first.should == 100
31
- @purgatory.requested_changes['price'].last.should == 200
26
+ expect(@purgatory.soul).to eq(@widget)
27
+ expect(@purgatory.requester).to eq(user1)
28
+ expect(@purgatory.requested_changes['name'].first).to eq('foo')
29
+ expect(@purgatory.requested_changes['name'].last).to eq('bar')
30
+ expect(@purgatory.requested_changes['price'].first).to eq(100)
31
+ expect(@purgatory.requested_changes['price'].last).to eq(200)
32
32
  end
33
33
 
34
34
  it "should return soul with changes if requested" do
35
35
  soul_with_changes = @purgatory.soul_with_changes
36
- soul_with_changes.name.should == 'bar'
37
- soul_with_changes.price.should == 200
36
+ expect(soul_with_changes.name).to eq('bar')
37
+ expect(soul_with_changes.price).to eq(200)
38
38
  end
39
39
 
40
+ it "should store attributes encrypted, but decrypt on access" do
41
+ raw_value = @purgatory.read_attribute(:requested_changes)
42
+ expect(raw_value['token']).to match([a_string_matching(/\A\{/), a_string_matching(/\A\{/)])
43
+
44
+ processed_value = @purgatory.requested_changes
45
+ expect(processed_value['token']).to eq(['tk_123', 'tk_456'])
46
+
47
+ soul_with_changes = @purgatory.soul_with_changes
48
+ expect(soul_with_changes.token).to eq('tk_456')
49
+ end
50
+
40
51
  it "should not change the widget" do
41
- @widget.name.should == 'foo'
42
- @widget.price.should == 100
52
+ expect(@widget.name).to eq('foo')
53
+ expect(@widget.price).to eq(100)
43
54
  end
44
55
 
45
56
  it "should allow the widget to access its purgatories" do
46
- @widget.purgatories.count.should == 1
47
- @widget.purgatories.first.should == @purgatory
57
+ expect(@widget.purgatories.count).to eq(1)
58
+ expect(@widget.purgatories.first).to eq(@purgatory)
48
59
  end
49
60
 
50
61
  it "should delete old pending purgatories with same soul" do
@@ -53,26 +64,26 @@ describe Purgatory do
53
64
  widget2_purgatory = @widget2.purgatory! user1
54
65
  @widget.name = 'baz'
55
66
  new_purgatory = @widget.purgatory! user1
56
- Purgatory.find_by_id(@purgatory.id).should be_nil
57
- Purgatory.find_by_id(widget2_purgatory.id).should be_present
58
- Purgatory.pending.count.should == 2
59
- Purgatory.last.requested_changes['name'].should == ['foo', 'baz']
67
+ expect(Purgatory.find_by_id(@purgatory.id)).to be_nil
68
+ expect(Purgatory.find_by_id(widget2_purgatory.id)).to be_present
69
+ expect(Purgatory.pending.count).to eq(2)
70
+ expect(Purgatory.last.requested_changes['name']).to eq(['foo', 'baz'])
60
71
  end
61
72
 
62
73
  it "should fail to create purgatory if matching pending Purgatory exists and fail_if_matching_soul is passed in" do
63
74
  @widget.name = 'baz'
64
75
  new_purgatory = @widget.purgatory! user1, fail_if_matching_soul: true
65
- new_purgatory.should be_nil
66
- Purgatory.find_by_id(@purgatory.id).should be_present
67
- Purgatory.pending.count.should == 1
76
+ expect(new_purgatory).to be_nil
77
+ expect(Purgatory.find_by_id(@purgatory.id)).to be_present
78
+ expect(Purgatory.pending.count).to eq(1)
68
79
  end
69
80
 
70
81
  it "should succeed to create purgatory if matching approved Purgatory exists and fail_if_matching_soul is passed in" do
71
82
  @purgatory.approve!
72
83
  @widget.name = 'baz'
73
84
  new_purgatory = @widget.purgatory! user1, fail_if_matching_soul: true
74
- new_purgatory.should be_present
75
- Purgatory.count.should == 2
85
+ expect(new_purgatory).to be_present
86
+ expect(Purgatory.count).to eq(2)
76
87
  end
77
88
  end
78
89
 
@@ -83,30 +94,30 @@ describe Purgatory do
83
94
  end
84
95
 
85
96
  it "should not change the object" do
86
- @item.name.should == 'foo'
87
- @item.price.should == 100
97
+ expect(@item.name).to eq('foo')
98
+ expect(@item.price).to eq(100)
88
99
  end
89
100
 
90
101
  it "should not save attr_accessor variable of object" do
91
- @item.dante.should == nil
102
+ expect(@item.dante).to eq(nil)
92
103
  end
93
104
 
94
105
  it "should store the attr_accessor variables in the Purgatory object" do
95
- @purgatory.attr_accessor_fields.should == { :@dante => "inferno" }
106
+ expect(@purgatory.attr_accessor_fields).to eq({ :@dante => "inferno" })
96
107
  end
97
108
 
98
109
  it "should return item with changed attr_accessor if requested" do
99
- @purgatory.soul_with_changes.dante.should == 'inferno'
110
+ expect(@purgatory.soul_with_changes.dante).to eq('inferno')
100
111
  end
101
112
  end
102
113
 
103
114
  it "should not allow invalid changes to be put into purgatory" do
104
115
  widget = Widget.create name: 'foo'
105
116
  widget.name = ''
106
- widget.purgatory!(user1).should be_nil
117
+ expect(widget.purgatory!(user1)).to be_nil
107
118
  widget.reload
108
- widget.name.should == 'foo'
109
- Purgatory.count.should be_zero
119
+ expect(widget.name).to eq('foo')
120
+ expect(Purgatory.count).to be_zero
110
121
  end
111
122
  end
112
123
 
@@ -115,30 +126,41 @@ describe Purgatory do
115
126
  before {create_new_object_purgatory}
116
127
 
117
128
  it "should create and return pending Purgatory object" do
118
- @purgatory.should be_present
119
- @purgatory.should_not be_approved
120
- @purgatory.should be_pending
121
- Purgatory.pending.count.should == 1
122
- Purgatory.pending.first.should == @purgatory
123
- Purgatory.approved.count.should be_zero
129
+ expect(@purgatory).to be_present
130
+ expect(@purgatory).not_to be_approved
131
+ expect(@purgatory).to be_pending
132
+ expect(Purgatory.pending.count).to eq(1)
133
+ expect(Purgatory.pending.first).to eq(@purgatory)
134
+ expect(Purgatory.approved.count).to be_zero
124
135
  end
125
136
 
126
137
  it "should return the soul as a new instance of the purgatoried class" do
127
138
  widget = @purgatory.soul
128
- widget.class.should == Widget
129
- widget.should be_new_record
139
+ expect(widget.class).to eq(Widget)
140
+ expect(widget).to be_new_record
141
+ end
142
+
143
+ it "should store attributes encrypted, but decrypt on access" do
144
+ raw_value = @purgatory.read_attribute(:requested_changes)
145
+ expect(raw_value['token']).to match([nil, a_string_matching(/\A\{/)])
146
+
147
+ processed_value = @purgatory.requested_changes
148
+ expect(processed_value['token']).to eq([nil, 'tk_123'])
149
+
150
+ soul_with_changes = @purgatory.soul_with_changes
151
+ expect(soul_with_changes.token).to eq('tk_123')
130
152
  end
131
153
 
132
154
  it "should store the requester and requested changes" do
133
- @purgatory.requester.should == user1
134
- @purgatory.requested_changes['name'].first.should == nil
135
- @purgatory.requested_changes['name'].last.should == 'foo'
136
- @purgatory.requested_changes['price'].first.should == nil
137
- @purgatory.requested_changes['price'].last.should == 100
155
+ expect(@purgatory.requester).to eq(user1)
156
+ expect(@purgatory.requested_changes['name'].first).to eq(nil)
157
+ expect(@purgatory.requested_changes['name'].last).to eq('foo')
158
+ expect(@purgatory.requested_changes['price'].first).to eq(nil)
159
+ expect(@purgatory.requested_changes['price'].last).to eq(100)
138
160
  end
139
161
 
140
162
  it "should not create a widget" do
141
- Widget.count.should be_zero
163
+ expect(Widget.count).to be_zero
142
164
  end
143
165
  end
144
166
 
@@ -146,28 +168,28 @@ describe Purgatory do
146
168
  before {create_new_object_purgatory_with_sti}
147
169
 
148
170
  it "should create and return pending Purgatory object" do
149
- @purgatory.should be_present
150
- @purgatory.should_not be_approved
151
- @purgatory.should be_pending
152
- Purgatory.pending.count.should == 1
153
- Purgatory.pending.first.should == @purgatory
154
- Purgatory.approved.count.should be_zero
171
+ expect(@purgatory).to be_present
172
+ expect(@purgatory).not_to be_approved
173
+ expect(@purgatory).to be_pending
174
+ expect(Purgatory.pending.count).to eq(1)
175
+ expect(Purgatory.pending.first).to eq(@purgatory)
176
+ expect(Purgatory.approved.count).to be_zero
155
177
  end
156
178
 
157
179
  it "should return the soul as a new instance of the purgatoried class" do
158
180
  dog = @purgatory.soul
159
- dog.class.should == Dog
160
- dog.should be_new_record
181
+ expect(dog.class).to eq(Dog)
182
+ expect(dog).to be_new_record
161
183
  end
162
184
 
163
185
  it "should store the requester and requested changes" do
164
- @purgatory.requester.should == user1
165
- @purgatory.requested_changes['name'].first.should == nil
166
- @purgatory.requested_changes['name'].last.should == 'doggy'
186
+ expect(@purgatory.requester).to eq(user1)
187
+ expect(@purgatory.requested_changes['name'].first).to eq(nil)
188
+ expect(@purgatory.requested_changes['name'].last).to eq('doggy')
167
189
  end
168
190
 
169
191
  it "should not create a dog" do
170
- Dog.count.should be_zero
192
+ expect(Dog.count).to be_zero
171
193
  end
172
194
  end
173
195
 
@@ -175,11 +197,11 @@ describe Purgatory do
175
197
  before {create_object_change_purgatory_with_sti}
176
198
 
177
199
  it "should delete old purgatory on object if new one is created" do
178
- Purgatory.count.should == 1
200
+ expect(Purgatory.count).to eq(1)
179
201
  @dog.name = 'fluffy'
180
202
  @dog.purgatory!(user1)
181
- Purgatory.last.requested_changes['name'].last.should == 'fluffy'
182
- Purgatory.count.should == 1
203
+ expect(Purgatory.last.requested_changes['name'].last).to eq('fluffy')
204
+ expect(Purgatory.count).to eq(1)
183
205
  end
184
206
  end
185
207
 
@@ -189,23 +211,23 @@ describe Purgatory do
189
211
  end
190
212
 
191
213
  it "should store the attr_accessor variables in the Purgatory object" do
192
- @purgatory.attr_accessor_fields.should == { :@dante => "inferno" }
214
+ expect(@purgatory.attr_accessor_fields).to eq({ :@dante => "inferno" })
193
215
  end
194
216
 
195
217
  it "should store the requester and requested changes" do
196
- @purgatory.requester.should == user1
197
- @purgatory.requested_changes['name'].first.should == nil
198
- @purgatory.requested_changes['name'].last.should == 'foo'
199
- @purgatory.requested_changes['price'].first.should == nil
200
- @purgatory.requested_changes['price'].last.should == 100
218
+ expect(@purgatory.requester).to eq(user1)
219
+ expect(@purgatory.requested_changes['name'].first).to eq(nil)
220
+ expect(@purgatory.requested_changes['name'].last).to eq('foo')
221
+ expect(@purgatory.requested_changes['price'].first).to eq(nil)
222
+ expect(@purgatory.requested_changes['price'].last).to eq(100)
201
223
  end
202
224
  end
203
225
 
204
226
  it "should not allow invalid object creation to be put into purgatory" do
205
227
  widget = Widget.new name: ''
206
- widget.purgatory!(user1).should be_nil
207
- Purgatory.count.should be_zero
208
- Widget.count.should be_zero
228
+ expect(widget.purgatory!(user1)).to be_nil
229
+ expect(Purgatory.count).to be_zero
230
+ expect(Widget.count).to be_zero
209
231
  end
210
232
  end
211
233
  end
@@ -214,50 +236,50 @@ describe Purgatory do
214
236
  context "approving object change purgatory" do
215
237
  before do
216
238
  create_object_change_purgatory
217
- @purgatory.approve!(user2).should be true
239
+ expect(@purgatory.approve!(user2)).to be true
218
240
  @widget.reload
219
241
  end
220
242
 
221
243
  it "should apply the changes" do
222
- @widget.name.should == 'bar'
223
- @widget.price.should == 200
244
+ expect(@widget.name).to eq('bar')
245
+ expect(@widget.price).to eq(200)
224
246
  end
225
247
 
226
248
  it "should mark purgatory as approved and store approver" do
227
- @purgatory.approver.should == user2
228
- @purgatory.should be_approved
229
- @purgatory.should_not be_pending
230
- Purgatory.pending.count.should be_zero
231
- Purgatory.approved.count.should == 1
232
- Purgatory.approved.first.should == @purgatory
249
+ expect(@purgatory.approver).to eq(user2)
250
+ expect(@purgatory).to be_approved
251
+ expect(@purgatory).not_to be_pending
252
+ expect(Purgatory.pending.count).to be_zero
253
+ expect(Purgatory.approved.count).to eq(1)
254
+ expect(Purgatory.approved.first).to eq(@purgatory)
233
255
  end
234
256
 
235
257
  it "should fail if you try to approve again" do
236
- @purgatory.approve!(user2).should be false
258
+ expect(@purgatory.approve!(user2)).to be false
237
259
  end
238
260
  end
239
261
 
240
262
  context "approving a performable method that returns false" do
241
263
  before do
242
264
  create_method_call_purgatory
243
- @purgatory.soul.stub(:rename).and_return(false)
265
+ allow(@purgatory.soul).to receive(:rename).and_return(false)
244
266
  end
245
267
 
246
268
  it "should store the soul, requester and performable_method" do
247
- @purgatory.soul.should == @widget
248
- @purgatory.requester.should == user1
249
- @purgatory.performable_method[:method].should == :rename
250
- @purgatory.performable_method[:args].should == ['bar']
269
+ expect(@purgatory.soul).to eq(@widget)
270
+ expect(@purgatory.requester).to eq(user1)
271
+ expect(@purgatory.performable_method[:method]).to eq(:rename)
272
+ expect(@purgatory.performable_method[:args]).to eq(['bar'])
251
273
  end
252
274
 
253
275
  it "should fail when performable method returns false" do
254
- @purgatory.approve!(user2).should be false
276
+ expect(@purgatory.approve!(user2)).to be false
255
277
  end
256
278
 
257
279
  it "it should not be approved" do
258
- @purgatory.should be_present
259
- @purgatory.should_not be_approved
260
- @purgatory.should be_pending
280
+ expect(@purgatory).to be_present
281
+ expect(@purgatory).not_to be_approved
282
+ expect(@purgatory).to be_pending
261
283
  end
262
284
  end
263
285
 
@@ -269,74 +291,74 @@ describe Purgatory do
269
291
  end
270
292
 
271
293
  it "should apply the changes" do
272
- @item.name.should == 'bar'
273
- @item.price.should == 200
294
+ expect(@item.name).to eq('bar')
295
+ expect(@item.price).to eq(200)
274
296
  end
275
297
 
276
298
  it "should apply changes that depend on attr_accessor instance_variable" do
277
- @item.original_name.should == "inferno"
299
+ expect(@item.original_name).to eq("inferno")
278
300
  end
279
301
 
280
302
  it "should mark purgatory as approved and store approver" do
281
- @purgatory.approver.should == user2
282
- @purgatory.should be_approved
283
- @purgatory.should_not be_pending
284
- Purgatory.pending.count.should be_zero
285
- Purgatory.approved.count.should == 1
286
- Purgatory.approved.first.should == @purgatory
303
+ expect(@purgatory.approver).to eq(user2)
304
+ expect(@purgatory).to be_approved
305
+ expect(@purgatory).not_to be_pending
306
+ expect(Purgatory.pending.count).to be_zero
307
+ expect(Purgatory.approved.count).to eq(1)
308
+ expect(Purgatory.approved.first).to eq(@purgatory)
287
309
  end
288
310
 
289
311
  it "should fail if you try to approve again" do
290
- @purgatory.approve!(user2).should be false
312
+ expect(@purgatory.approve!(user2)).to be false
291
313
  end
292
314
  end
293
315
 
294
316
  context "approving new object creation" do
295
317
  before do
296
318
  create_new_object_purgatory
297
- @purgatory.approve!(user2).should be true
319
+ expect(@purgatory.approve!(user2)).to be true
298
320
  end
299
321
 
300
322
  it "should create the new object and apply any callbacks" do
301
- Widget.count.should == 1
323
+ expect(Widget.count).to eq(1)
302
324
  widget = Widget.first
303
- widget.name.should == 'foo'
304
- widget.price.should == 100
305
- widget.original_name.should == 'foo'
325
+ expect(widget.name).to eq('foo')
326
+ expect(widget.price).to eq(100)
327
+ expect(widget.original_name).to eq('foo')
306
328
  end
307
329
 
308
330
  it "should mark purgatory as approved and store approver" do
309
- @purgatory.approver.should == user2
310
- @purgatory.should be_approved
311
- @purgatory.should_not be_pending
312
- Purgatory.pending.count.should be_zero
313
- Purgatory.approved.count.should == 1
314
- Purgatory.approved.first.should == @purgatory
331
+ expect(@purgatory.approver).to eq(user2)
332
+ expect(@purgatory).to be_approved
333
+ expect(@purgatory).not_to be_pending
334
+ expect(Purgatory.pending.count).to be_zero
335
+ expect(Purgatory.approved.count).to eq(1)
336
+ expect(Purgatory.approved.first).to eq(@purgatory)
315
337
  end
316
338
 
317
339
  it "should store the id of the newly created object so the purgatory can be accessed through the object" do
318
340
  widget = Widget.first
319
- widget.purgatories.count.should == 1
320
- widget.purgatories.first.should == @purgatory
341
+ expect(widget.purgatories.count).to eq(1)
342
+ expect(widget.purgatories.first).to eq(@purgatory)
321
343
  end
322
344
 
323
345
  it "should fail if you try to approve again" do
324
- @purgatory.approve!(user2).should be false
346
+ expect(@purgatory.approve!(user2)).to be false
325
347
  end
326
348
  end
327
349
 
328
350
  context "approving new object creation using STI" do
329
351
  before do
330
352
  create_new_object_purgatory_with_sti
331
- @purgatory.approve!(user2).should be true
353
+ expect(@purgatory.approve!(user2)).to be true
332
354
  end
333
355
 
334
356
  it "should create the new object and apply any callbacks" do
335
- Dog.count.should == 1
357
+ expect(Dog.count).to eq(1)
336
358
  dog = Dog.first
337
- dog.name.should == 'doggy'
338
- dog.original_name.should == 'doggy'
339
- dog.price.should == Dog::DEFAULT_PRICE
359
+ expect(dog.name).to eq('doggy')
360
+ expect(dog.original_name).to eq('doggy')
361
+ expect(dog.price).to eq(Dog::DEFAULT_PRICE)
340
362
  end
341
363
  end
342
364
 
@@ -347,37 +369,37 @@ describe Purgatory do
347
369
  end
348
370
 
349
371
  it "should create the new object and apply any callbacks" do
350
- Item.count.should == 1
372
+ expect(Item.count).to eq(1)
351
373
  item = Item.first
352
- item.name.should == 'foo'
353
- item.price.should == 100
374
+ expect(item.name).to eq('foo')
375
+ expect(item.price).to eq(100)
354
376
  end
355
377
 
356
378
  it "should apply changes that depend on attr_accessor instance_variable" do
357
- Item.first.original_name.should == 'inferno'
379
+ expect(Item.first.original_name).to eq('inferno')
358
380
  end
359
381
 
360
382
  it "should mark purgatory as approved and store approver" do
361
- @purgatory.approver.should == user2
362
- @purgatory.should be_approved
363
- @purgatory.should_not be_pending
364
- Purgatory.pending.count.should be_zero
365
- Purgatory.approved.count.should == 1
366
- Purgatory.approved.first.should == @purgatory
383
+ expect(@purgatory.approver).to eq(user2)
384
+ expect(@purgatory).to be_approved
385
+ expect(@purgatory).not_to be_pending
386
+ expect(Purgatory.pending.count).to be_zero
387
+ expect(Purgatory.approved.count).to eq(1)
388
+ expect(Purgatory.approved.first).to eq(@purgatory)
367
389
  end
368
390
 
369
391
  it "should fail if you try to approve again" do
370
- @purgatory.approve!(user2).should be false
392
+ expect(@purgatory.approve!(user2)).to be false
371
393
  end
372
394
  end
373
395
 
374
396
  context "approving method call purgatory" do
375
397
  before{create_method_call_purgatory}
376
398
  it "should call the method" do
377
- @widget.name.should == 'foo'
399
+ expect(@widget.name).to eq('foo')
378
400
  @purgatory.approve!
379
401
  @widget.reload
380
- @widget.name.should == 'bar'
402
+ expect(@widget.name).to eq('bar')
381
403
  end
382
404
  end
383
405
  end
@@ -393,7 +415,7 @@ describe Purgatory do
393
415
  it "should not store attr_accessors" do
394
416
  obj = @klass.new name: 'foo', price: 100, dante: "inferno"
395
417
  purgatory = obj.purgatory! user1
396
- purgatory.attr_accessor_fields.should == {}
418
+ expect(purgatory.attr_accessor_fields).to eq({})
397
419
  end
398
420
  end
399
421
 
@@ -407,7 +429,7 @@ describe Purgatory do
407
429
  it "should work" do
408
430
  obj = @klass.new name: 'foo', price: 100, dante: "inferno"
409
431
  purgatory = obj.purgatory! user1
410
- purgatory.attr_accessor_fields.should == { :@dante => "inferno" }
432
+ expect(purgatory.attr_accessor_fields).to eq({ :@dante => "inferno" })
411
433
  end
412
434
  end
413
435
 
@@ -426,15 +448,15 @@ describe Purgatory do
426
448
  it "should work" do
427
449
  obj = @klass.new name: 'foo', price: 100, dante: "inferno"
428
450
  purgatory = obj.purgatory! user1
429
- purgatory.attr_accessor_fields.should == { :@dante => "inferno" }
451
+ expect(purgatory.attr_accessor_fields).to eq({ :@dante => "inferno" })
430
452
 
431
453
  obj = @klass_2.new name: 'foo', price: 100, minos: "inferno"
432
454
  purgatory = obj.purgatory! user1
433
- purgatory.attr_accessor_fields.should == { :@minos => "inferno" }
455
+ expect(purgatory.attr_accessor_fields).to eq({ :@minos => "inferno" })
434
456
 
435
457
  obj = @klass_3.new name: 'foo', price: 100
436
458
  purgatory = obj.purgatory! user1
437
- purgatory.attr_accessor_fields.should == {}
459
+ expect(purgatory.attr_accessor_fields).to eq({})
438
460
  end
439
461
  end
440
462
  end
@@ -448,7 +470,7 @@ describe Purgatory do
448
470
  end
449
471
 
450
472
  it "should not contain any thing" do
451
- AttributeAccessorFields.determine_attr_accessor_fields(@obj).should == {}
473
+ expect(AttributeAccessorFields.determine_attr_accessor_fields(@obj)).to eq({})
452
474
  end
453
475
  end
454
476
 
@@ -466,7 +488,7 @@ describe Purgatory do
466
488
 
467
489
  context "local_attributes is empty" do
468
490
  it "should not contain any attr_accessor values" do
469
- AttributeAccessorFields.determine_attr_accessor_fields(@obj).should == {}
491
+ expect(AttributeAccessorFields.determine_attr_accessor_fields(@obj)).to eq({})
470
492
  end
471
493
  end
472
494
 
@@ -477,7 +499,7 @@ describe Purgatory do
477
499
  end
478
500
 
479
501
  it "should only contain attr_accessors specified in array" do
480
- AttributeAccessorFields.determine_attr_accessor_fields(@obj).should == { :@dante => "inferno" }
502
+ expect(AttributeAccessorFields.determine_attr_accessor_fields(@obj)).to eq({ :@dante => "inferno" })
481
503
  end
482
504
  end
483
505
  context "array size is more than 1" do
@@ -486,7 +508,7 @@ describe Purgatory do
486
508
  end
487
509
 
488
510
  it "should only contain attr_accessors specified in array" do
489
- AttributeAccessorFields.determine_attr_accessor_fields(@obj).should == { :@dante => "inferno", :@minos => "inferno" }
511
+ expect(AttributeAccessorFields.determine_attr_accessor_fields(@obj)).to eq({ :@dante => "inferno", :@minos => "inferno" })
490
512
  end
491
513
 
492
514
  end
@@ -498,7 +520,7 @@ describe Purgatory do
498
520
  end
499
521
 
500
522
  it "should automatically determine attr_accessor values that doesnt include ones belonging to AR::Base and its ancestors, and then store these values" do
501
- AttributeAccessorFields.determine_attr_accessor_fields(@obj).should == { :@dante => "inferno", :@minos => "inferno", :@charon => "inferno" }
523
+ expect(AttributeAccessorFields.determine_attr_accessor_fields(@obj)).to eq({ :@dante => "inferno", :@minos => "inferno", :@charon => "inferno" })
502
524
  end
503
525
  end
504
526
  end
@@ -519,7 +541,7 @@ describe Purgatory do
519
541
  end
520
542
 
521
543
  it "should not include instance_variables that belong to ancestor of ActiveRecord::Base" do
522
- ActiveRecordDescendantAttributeAccessors.attr_accessor_instance_variables(@widget).should == []
544
+ expect(ActiveRecordDescendantAttributeAccessors.attr_accessor_instance_variables(@widget)).to eq([])
523
545
  end
524
546
  end
525
547
 
@@ -536,7 +558,7 @@ describe Purgatory do
536
558
  end
537
559
 
538
560
  it "should not include instance_variables that belong to ActiveRecord::Base" do
539
- ActiveRecordDescendantAttributeAccessors.attr_accessor_instance_variables(@widget).should == []
561
+ expect(ActiveRecordDescendantAttributeAccessors.attr_accessor_instance_variables(@widget)).to eq([])
540
562
  end
541
563
  end
542
564
 
@@ -552,7 +574,7 @@ describe Purgatory do
552
574
  end
553
575
 
554
576
  it "should include instance_variables from attr_accessors that belong to descendant of ActiveRecord::Base" do
555
- ActiveRecordDescendantAttributeAccessors.attr_accessor_instance_variables(@widget).should == [:@dante]
577
+ expect(ActiveRecordDescendantAttributeAccessors.attr_accessor_instance_variables(@widget)).to eq([:@dante])
556
578
  end
557
579
  end
558
580
 
@@ -568,7 +590,7 @@ describe Purgatory do
568
590
  end
569
591
 
570
592
  it "should include instance_variables from attr_accessors that belong to descendant of ActiveRecord::Base" do
571
- ActiveRecordDescendantAttributeAccessors.attr_accessor_instance_variables(@widget).should == [:@dante]
593
+ expect(ActiveRecordDescendantAttributeAccessors.attr_accessor_instance_variables(@widget)).to eq([:@dante])
572
594
  end
573
595
  end
574
596
 
@@ -582,7 +604,7 @@ describe Purgatory do
582
604
  end
583
605
 
584
606
  it "should include instance_variables from attr_accessors that belong to descendant of ActiveRecord::Base" do
585
- ActiveRecordDescendantAttributeAccessors.attr_accessor_instance_variables(@widget).should == [:@dante]
607
+ expect(ActiveRecordDescendantAttributeAccessors.attr_accessor_instance_variables(@widget)).to eq([:@dante])
586
608
  end
587
609
  end
588
610
  end
@@ -592,19 +614,19 @@ describe Purgatory do
592
614
  before {create_method_call_purgatory}
593
615
 
594
616
  it "should create and return pending Purgatory object" do
595
- @purgatory.should be_present
596
- @purgatory.should_not be_approved
597
- @purgatory.should be_pending
598
- Purgatory.pending.count.should == 1
599
- Purgatory.pending.first.should == @purgatory
600
- Purgatory.approved.count.should be_zero
617
+ expect(@purgatory).to be_present
618
+ expect(@purgatory).not_to be_approved
619
+ expect(@purgatory).to be_pending
620
+ expect(Purgatory.pending.count).to eq(1)
621
+ expect(Purgatory.pending.first).to eq(@purgatory)
622
+ expect(Purgatory.approved.count).to be_zero
601
623
  end
602
624
 
603
625
  it "should store the soul, requester and performable_method" do
604
- @purgatory.soul.should == @widget
605
- @purgatory.requester.should == user1
606
- @purgatory.performable_method[:method].should == :rename
607
- @purgatory.performable_method[:args].should == ['bar']
626
+ expect(@purgatory.soul).to eq(@widget)
627
+ expect(@purgatory.requester).to eq(user1)
628
+ expect(@purgatory.performable_method[:method]).to eq(:rename)
629
+ expect(@purgatory.performable_method[:args]).to eq(['bar'])
608
630
  end
609
631
 
610
632
  it "should delete old pending purgatories with same soul" do
@@ -613,26 +635,26 @@ describe Purgatory do
613
635
  widget2_purgatory = @widget2.purgatize(user1).rename('bar')
614
636
  @widget.name = 'baz'
615
637
  new_purgatory = @widget.purgatize(user1).rename('bar')
616
- Purgatory.find_by_id(@purgatory.id).should be_nil
617
- Purgatory.find_by_id(widget2_purgatory.id).should be_present
618
- Purgatory.pending.count.should == 2
619
- Purgatory.last.requested_changes['name'].should == ['foo', 'baz']
638
+ expect(Purgatory.find_by_id(@purgatory.id)).to be_nil
639
+ expect(Purgatory.find_by_id(widget2_purgatory.id)).to be_present
640
+ expect(Purgatory.pending.count).to eq(2)
641
+ expect(Purgatory.last.requested_changes['name']).to eq(['foo', 'baz'])
620
642
  end
621
643
 
622
644
  it "should fail to create purgatory if matching pending Purgatory exists and fail_if_matching_soul is passed in" do
623
645
  @widget.name = 'baz'
624
646
  new_purgatory = @widget.purgatize(user1, fail_if_matching_soul: true).rename('bar')
625
- new_purgatory.should be_nil
626
- Purgatory.find_by_id(@purgatory.id).should be_present
627
- Purgatory.pending.count.should == 1
647
+ expect(new_purgatory).to be_nil
648
+ expect(Purgatory.find_by_id(@purgatory.id)).to be_present
649
+ expect(Purgatory.pending.count).to eq(1)
628
650
  end
629
651
 
630
652
  it "should succeed to create purgatory if matching approved Purgatory exists and fail_if_matching_soul is passed in" do
631
653
  @purgatory.approve!
632
654
  @widget.name = 'baz'
633
655
  new_purgatory = @widget.purgatize(user1, fail_if_matching_soul: true).rename('bar')
634
- new_purgatory.should be_present
635
- Purgatory.count.should == 2
656
+ expect(new_purgatory).to be_present
657
+ expect(Purgatory.count).to eq(2)
636
658
  end
637
659
  end
638
660
  end
@@ -642,9 +664,10 @@ describe Purgatory do
642
664
  private
643
665
 
644
666
  def create_object_change_purgatory
645
- @widget = Widget.create name: 'foo', price: 100
667
+ @widget = Widget.create name: 'foo', price: 100, token: 'tk_123'
646
668
  @widget.name = 'bar'
647
669
  @widget.price = 200
670
+ @widget.token = 'tk_456'
648
671
  purgatory = @widget.purgatory! user1
649
672
  @purgatory = Purgatory.find(purgatory.id)
650
673
  @widget.reload
@@ -658,7 +681,7 @@ describe Purgatory do
658
681
  end
659
682
 
660
683
  def create_new_object_purgatory
661
- widget = Widget.new name: 'foo', price: 100
684
+ widget = Widget.new name: 'foo', price: 100, token: 'tk_123'
662
685
  purgatory = widget.purgatory! user1
663
686
  @purgatory = Purgatory.find(purgatory.id)
664
687
  end
@@ -1,12 +1,19 @@
1
1
  require 'active_record'
2
- require 'generators/purgatory/templates/create_purgatories'
3
- require 'generators/purgatory/templates/add_performable_method_to_purgatories'
4
2
  require 'purgatory/purgatory_module'
5
3
 
6
4
  ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
7
5
 
6
+ ActiveRecord.use_yaml_unsafe_load = true
7
+
8
+ ActiveRecord::Encryption.configure(
9
+ primary_key: 'abc123',
10
+ deterministic_key: 'def456',
11
+ key_derivation_salt: 'ghi789',
12
+ )
13
+
8
14
  ActiveRecord::Migration.create_table :widgets do |t|
9
15
  t.string :name
16
+ t.string :token, limit: 510
10
17
  t.integer :price
11
18
  t.string :original_name
12
19
  t.timestamps
@@ -31,8 +38,21 @@ ActiveRecord::Migration.create_table :items do |t|
31
38
  t.timestamps
32
39
  end
33
40
 
34
- CreatePurgatories.new.migrate(:up)
35
- AddPerformableMethodToPurgatories.new.migrate(:up)
41
+ ActiveRecord::Migration.create_table :purgatories do |t|
42
+ t.integer :soul_id
43
+ t.string :soul_type
44
+ t.integer :requester_id
45
+ t.integer :approver_id
46
+ t.datetime :approved_at
47
+ t.text :requested_changes
48
+ t.text :attr_accessor_fields
49
+ t.text :performable_method
50
+ t.timestamps
51
+
52
+ t.index [:soul_id, :soul_type]
53
+ t.index :requester_id
54
+ t.index :approver_id
55
+ end
36
56
 
37
57
  PurgatoryModule.configure do |config|
38
58
  config.user_class_name = 'User'
@@ -5,8 +5,10 @@ class Widget < ActiveRecord::Base
5
5
  validates :name, presence: true
6
6
  before_create :set_original_name
7
7
 
8
+ encrypts :token
9
+
8
10
  def rename(new_name)
9
- self.update_attributes(name: new_name)
11
+ self.update(name: new_name)
10
12
  end
11
13
 
12
14
  private
@@ -14,4 +16,4 @@ class Widget < ActiveRecord::Base
14
16
  def set_original_name
15
17
  self.original_name = name
16
18
  end
17
- end
19
+ end
metadata CHANGED
@@ -1,11 +1,11 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: purgatory
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.0.3
4
+ version: 6.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Elan Dubrofsky
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
  date: 2017-08-24 00:00:00.000000000 Z
@@ -21,16 +21,14 @@ extra_rdoc_files:
21
21
  files:
22
22
  - ".document"
23
23
  - ".rspec"
24
- - ".travis.yml"
25
24
  - Gemfile
26
- - Gemfile.lock
27
25
  - LICENSE.txt
28
26
  - README.markdown
29
27
  - VERSION
30
28
  - init.rb
31
29
  - lib/generators/purgatory/purgatory_generator.rb
32
- - lib/generators/purgatory/templates/add_performable_method_to_purgatories.rb
33
- - lib/generators/purgatory/templates/create_purgatories.rb
30
+ - lib/generators/purgatory/templates/add_performable_method_to_purgatories.rb.erb
31
+ - lib/generators/purgatory/templates/create_purgatories.rb.erb
34
32
  - lib/purgatory.rb
35
33
  - lib/purgatory/active_record_descendant_attribute_accessors.rb
36
34
  - lib/purgatory/attribute_accessor_fields.rb
@@ -47,7 +45,7 @@ homepage: http://github.com/financeit/purgatory
47
45
  licenses:
48
46
  - MIT
49
47
  metadata: {}
50
- post_install_message:
48
+ post_install_message:
51
49
  rdoc_options: []
52
50
  require_paths:
53
51
  - lib
@@ -62,8 +60,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
62
60
  - !ruby/object:Gem::Version
63
61
  version: '0'
64
62
  requirements: []
65
- rubygems_version: 3.5.15
66
- signing_key:
63
+ rubygems_version: 3.0.3.1
64
+ signing_key:
67
65
  specification_version: 4
68
66
  summary: Allow changes to a model to be put in purgatory until they are approved
69
67
  test_files: []
data/.travis.yml DELETED
@@ -1,10 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 2.2.10
4
- - 2.3.8
5
- - 2.4.9
6
- - 2.5.7
7
- - 2.6.5
8
- cache:
9
- bundler: true
10
- script: bundle exec rspec
data/Gemfile.lock DELETED
@@ -1,53 +0,0 @@
1
- GEM
2
- remote: http://rubygems.org/
3
- specs:
4
- activemodel (4.2.11.1)
5
- activesupport (= 4.2.11.1)
6
- builder (~> 3.1)
7
- activerecord (4.2.11.1)
8
- activemodel (= 4.2.11.1)
9
- activesupport (= 4.2.11.1)
10
- arel (~> 6.0)
11
- activesupport (4.2.11.1)
12
- i18n (~> 0.7)
13
- minitest (~> 5.1)
14
- thread_safe (~> 0.3, >= 0.3.4)
15
- tzinfo (~> 1.1)
16
- arel (6.0.4)
17
- builder (3.2.4)
18
- coderay (1.1.0)
19
- concurrent-ruby (1.1.6)
20
- diff-lcs (1.2.5)
21
- i18n (0.9.5)
22
- concurrent-ruby (~> 1.0)
23
- method_source (0.8.2)
24
- minitest (5.14.0)
25
- pry (0.9.12.4)
26
- coderay (~> 1.0)
27
- method_source (~> 0.8)
28
- slop (~> 3.4)
29
- rspec (2.14.1)
30
- rspec-core (~> 2.14.0)
31
- rspec-expectations (~> 2.14.0)
32
- rspec-mocks (~> 2.14.0)
33
- rspec-core (2.14.7)
34
- rspec-expectations (2.14.4)
35
- diff-lcs (>= 1.1.3, < 2.0)
36
- rspec-mocks (2.14.4)
37
- slop (3.4.7)
38
- sqlite3 (1.3.13)
39
- thread_safe (0.3.6)
40
- tzinfo (1.2.6)
41
- thread_safe (~> 0.1)
42
-
43
- PLATFORMS
44
- ruby
45
-
46
- DEPENDENCIES
47
- activerecord (~> 4.1)
48
- pry
49
- rspec
50
- sqlite3
51
-
52
- BUNDLED WITH
53
- 1.17.3