cia 0.3.7 → 0.4.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.
data/Appraisals CHANGED
@@ -1,5 +1,6 @@
1
1
  appraise "rails2" do
2
2
  gem 'activerecord', "2.3.14"
3
+ gem 'after_commit'
3
4
  end
4
5
 
5
6
  appraise "rails3" do
@@ -1,42 +1,42 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cia (0.3.7)
4
+ cia (0.4.0)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
8
8
  specs:
9
- activemodel (3.2.2)
10
- activesupport (= 3.2.2)
9
+ activemodel (3.2.11)
10
+ activesupport (= 3.2.11)
11
11
  builder (~> 3.0.0)
12
- activerecord (3.2.2)
13
- activemodel (= 3.2.2)
14
- activesupport (= 3.2.2)
12
+ activerecord (3.2.11)
13
+ activemodel (= 3.2.11)
14
+ activesupport (= 3.2.11)
15
15
  arel (~> 3.0.2)
16
16
  tzinfo (~> 0.3.29)
17
- activesupport (3.2.2)
17
+ activesupport (3.2.11)
18
18
  i18n (~> 0.6)
19
19
  multi_json (~> 1.0)
20
- appraisal (0.4.1)
20
+ appraisal (0.5.1)
21
21
  bundler
22
22
  rake
23
23
  arel (3.0.2)
24
- builder (3.0.0)
25
- bump (0.3.7)
24
+ builder (3.0.4)
25
+ bump (0.3.9)
26
26
  diff-lcs (1.1.3)
27
- i18n (0.6.0)
28
- multi_json (1.3.4)
29
- rake (0.9.2)
30
- rspec (2.6.0)
31
- rspec-core (~> 2.6.0)
32
- rspec-expectations (~> 2.6.0)
33
- rspec-mocks (~> 2.6.0)
34
- rspec-core (2.6.4)
35
- rspec-expectations (2.6.0)
36
- diff-lcs (~> 1.1.2)
37
- rspec-mocks (2.6.0)
27
+ i18n (0.6.1)
28
+ multi_json (1.5.0)
29
+ rake (10.0.3)
30
+ rspec (2.12.0)
31
+ rspec-core (~> 2.12.0)
32
+ rspec-expectations (~> 2.12.0)
33
+ rspec-mocks (~> 2.12.0)
34
+ rspec-core (2.12.2)
35
+ rspec-expectations (2.12.1)
36
+ diff-lcs (~> 1.1.3)
37
+ rspec-mocks (2.12.1)
38
38
  sqlite3 (1.3.6)
39
- tzinfo (0.3.33)
39
+ tzinfo (0.3.35)
40
40
 
41
41
  PLATFORMS
42
42
  ruby
@@ -2,10 +2,12 @@
2
2
 
3
3
  source :rubygems
4
4
 
5
+ gem "bump"
5
6
  gem "rake"
6
7
  gem "rspec", "~>2"
7
8
  gem "appraisal"
8
9
  gem "sqlite3"
9
10
  gem "activerecord", "2.3.14"
11
+ gem "after_commit"
10
12
 
11
13
  gemspec :path=>"../"
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: /Users/mgrosser/code/tools/cia
3
3
  specs:
4
- cia (0.3.6)
4
+ cia (0.3.7)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
@@ -9,9 +9,12 @@ GEM
9
9
  activerecord (2.3.14)
10
10
  activesupport (= 2.3.14)
11
11
  activesupport (2.3.14)
12
+ after_commit (1.0.10)
13
+ activerecord (>= 1.15.6, < 3.0.0)
12
14
  appraisal (0.4.1)
13
15
  bundler
14
16
  rake
17
+ bump (0.3.9)
15
18
  diff-lcs (1.1.3)
16
19
  rake (0.9.2.2)
17
20
  rspec (2.10.0)
@@ -29,7 +32,9 @@ PLATFORMS
29
32
 
30
33
  DEPENDENCIES
31
34
  activerecord (= 2.3.14)
35
+ after_commit
32
36
  appraisal
37
+ bump
33
38
  cia!
34
39
  rake
35
40
  rspec (~> 2)
@@ -2,6 +2,7 @@
2
2
 
3
3
  source :rubygems
4
4
 
5
+ gem "bump"
5
6
  gem "rake"
6
7
  gem "rspec", "~>2"
7
8
  gem "appraisal"
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: /Users/mgrosser/code/tools/cia
3
3
  specs:
4
- cia (0.3.6)
4
+ cia (0.3.7)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
@@ -17,25 +17,26 @@ GEM
17
17
  activesupport (3.2.3)
18
18
  i18n (~> 0.6)
19
19
  multi_json (~> 1.0)
20
- appraisal (0.4.1)
20
+ appraisal (0.5.1)
21
21
  bundler
22
22
  rake
23
23
  arel (3.0.2)
24
- builder (3.0.0)
24
+ builder (3.0.4)
25
+ bump (0.3.9)
25
26
  diff-lcs (1.1.3)
26
- i18n (0.6.0)
27
- multi_json (1.3.5)
28
- rake (0.9.2.2)
29
- rspec (2.10.0)
30
- rspec-core (~> 2.10.0)
31
- rspec-expectations (~> 2.10.0)
32
- rspec-mocks (~> 2.10.0)
33
- rspec-core (2.10.1)
34
- rspec-expectations (2.10.0)
27
+ i18n (0.6.1)
28
+ multi_json (1.5.0)
29
+ rake (10.0.3)
30
+ rspec (2.12.0)
31
+ rspec-core (~> 2.12.0)
32
+ rspec-expectations (~> 2.12.0)
33
+ rspec-mocks (~> 2.12.0)
34
+ rspec-core (2.12.2)
35
+ rspec-expectations (2.12.1)
35
36
  diff-lcs (~> 1.1.3)
36
- rspec-mocks (2.10.1)
37
+ rspec-mocks (2.12.1)
37
38
  sqlite3 (1.3.6)
38
- tzinfo (0.3.33)
39
+ tzinfo (0.3.35)
39
40
 
40
41
  PLATFORMS
41
42
  ruby
@@ -43,6 +44,7 @@ PLATFORMS
43
44
  DEPENDENCIES
44
45
  activerecord (= 3.2.3)
45
46
  appraisal
47
+ bump
46
48
  cia!
47
49
  rake
48
50
  rspec (~> 2)
@@ -1,11 +1,8 @@
1
1
  module CIA
2
2
  module Auditable
3
3
  def self.included(base)
4
- base.class_attribute :audited_attributes, :audited_attribute_options
4
+ base.class_attribute :audited_attributes, :audited_attribute_options, :audited_attributes_callbacks_added
5
5
  base.send :extend, ClassMethods
6
- base.after_create {|record| CIA.record(:create, record) }
7
- base.after_update {|record| CIA.record(:update, record) }
8
- base.after_destroy {|record| CIA.record(:destroy, record) }
9
6
  end
10
7
 
11
8
  def cia_changes
@@ -15,17 +12,34 @@ module CIA
15
12
  module ClassMethods
16
13
  def audit_attribute(*attributes)
17
14
  options = (attributes.last.is_a?(Hash) ? attributes.pop : {})
15
+ setup_auditing_callbacks(options)
18
16
 
19
- self.audited_attributes = Set.new unless audited_attributes
20
- self.audited_attributes += attributes.map(&:to_s)
17
+ self.audited_attributes = attributes.map(&:to_s)
21
18
 
22
19
  raise "cannot have :if and :unless" if options[:if] && options[:unless]
23
- self.audited_attribute_options ||= {}
24
- self.audited_attribute_options.merge!(options)
20
+ self.audited_attribute_options = options
25
21
 
26
22
  has_many :cia_events, :class_name => "CIA::Event", :as => :source
27
23
  has_many :cia_attribute_changes, :class_name => "CIA::AttributeChange", :as => :source
28
24
  end
25
+
26
+ def setup_auditing_callbacks(options)
27
+ return if audited_attributes_callbacks_added
28
+ self.audited_attributes_callbacks_added = true
29
+
30
+ [:create, :update, :destroy].each do |callback|
31
+ method, args = if options[:callback] == :after_commit
32
+ if ActiveRecord::VERSION::MAJOR == 2
33
+ ["after_commit_on_#{callback}"]
34
+ else # rails 3+
35
+ [:after_commit, [{:on => callback}]]
36
+ end
37
+ else
38
+ ["after_#{callback}", []]
39
+ end
40
+ send(method, *args) { |record| CIA.record(callback, record) }
41
+ end
42
+ end
29
43
  end
30
44
  end
31
45
  end
@@ -1,3 +1,3 @@
1
1
  module CIA
2
- VERSION = '0.3.7'
2
+ VERSION = '0.4.0'
3
3
  end
@@ -84,6 +84,65 @@ describe CIA do
84
84
  CIA::Event.last.action.should == "update"
85
85
  end
86
86
 
87
+ it "does not track failed changes" do
88
+ car = Car.create!(:wheels => 1).id
89
+ expect{
90
+ expect{ FailCar.new(:wheels => 4).save }.to raise_error(FailCar::Oops)
91
+ car = FailCar.find(car)
92
+ expect{ car.update_attributes(:wheels => 2) }.to raise_error(FailCar::Oops)
93
+ expect{ car.destroy }.to raise_error(FailCar::Oops)
94
+ }.to_not change{ CIA::Event.count }
95
+ end
96
+
97
+ it "is rolled back if auditing fails" do
98
+ CIA.should_receive(:record).and_raise("XXX")
99
+ expect{
100
+ expect{
101
+ CIA.audit{ object.save! }
102
+ }.to raise_error("XXX")
103
+ }.to_not change{ object.class.count }
104
+ end
105
+
106
+ context "nested classes with multiple audited_attributes" do
107
+ let(:object){ NestedCar.new }
108
+
109
+ it "has the exclusive sub-classes attributes of the nested class" do
110
+ object.class.audited_attributes.should == ["drivers"]
111
+ end
112
+
113
+ it "does not record twice for nested classes" do
114
+ expect{
115
+ CIA.audit{ object.save! }
116
+ }.to change{ CIA::Event.count }.by(+1)
117
+ end
118
+
119
+ it "does not record twice for super classes" do
120
+ expect{
121
+ CIA.audit{ Car.new.save! }
122
+ }.to change{ CIA::Event.count }.by(+1)
123
+ end
124
+ end
125
+
126
+ context "nested classes with 1 audited_attributes" do
127
+ let(:object){ InheritedCar.new }
128
+
129
+ it "has the super-classes attributes" do
130
+ object.class.audited_attributes.should == ["wheels"]
131
+ end
132
+
133
+ it "does not record twice for nested classes" do
134
+ expect{
135
+ CIA.audit{ object.save! }
136
+ }.to change{ CIA::Event.count }.by(+1)
137
+ end
138
+
139
+ it "does not record twice for super classes" do
140
+ expect{
141
+ CIA.audit{ Car.new.save! }
142
+ }.to change{ CIA::Event.count }.by(+1)
143
+ end
144
+ end
145
+
87
146
  context "custom changes" do
88
147
  let(:object) { CarWithCustomChanges.new }
89
148
 
@@ -254,6 +313,28 @@ describe CIA do
254
313
  ex.inspect.should == '#<StandardError: foo>'
255
314
  end
256
315
  end
316
+
317
+ context "with after_commit" do
318
+ let(:object){ CarWithTransactions.new }
319
+
320
+ it "still tracks" do
321
+ expect{
322
+ CIA.audit{ object.save! }
323
+ }.to change{ CIA::Event.count }.by(+1)
324
+ end
325
+
326
+ it "is not rolled back if auditing fails" do
327
+ CIA.should_receive(:record).and_raise("XXX")
328
+ begin
329
+ expect{
330
+ CIA.audit{ object.save! }
331
+ }.to change{ object.class.count }.by(+1)
332
+ rescue RuntimeError => e
333
+ # errors from after_commit are never raised in rails 3+
334
+ raise e if ActiveRecord::VERSION::MAJOR != 2 || e.message != "XXX"
335
+ end
336
+ end
337
+ end
257
338
  end
258
339
 
259
340
  context ".current_actor" do
@@ -1,5 +1,6 @@
1
1
  $LOAD_PATH.unshift 'lib'
2
2
  require 'cia'
3
+ require 'after_commit' if ActiveRecord::VERSION::MAJOR == 2
3
4
 
4
5
  RSpec.configure do |config|
5
6
  config.before do
@@ -45,8 +46,7 @@ end
45
46
  class CarWith3Attributes < ActiveRecord::Base
46
47
  self.table_name = "cars"
47
48
  include CIA::Auditable
48
- audit_attribute :wheels, :color
49
- audit_attribute :drivers
49
+ audit_attribute :wheels, :color, :drivers
50
50
  end
51
51
 
52
52
  class CarWithIf < ActiveRecord::Base
@@ -73,6 +73,32 @@ class CarWithCustomChanges < ActiveRecord::Base
73
73
  end
74
74
  end
75
75
 
76
+ class FailCar < ActiveRecord::Base
77
+ self.table_name = "cars"
78
+ include CIA::Auditable
79
+ audit_attribute :wheels
80
+
81
+ class Oops < Exception
82
+ end
83
+
84
+ after_update { |x| raise Oops }
85
+ after_create { |x| raise Oops }
86
+ after_destroy { |x| raise Oops }
87
+ end
88
+
89
+ class CarWithTransactions < ActiveRecord::Base
90
+ self.table_name = "cars"
91
+ include CIA::Auditable
92
+ audit_attribute :wheels, :callback => :after_commit
93
+ end
94
+
95
+ class NestedCar < Car
96
+ audit_attribute :drivers
97
+ end
98
+
99
+ class InheritedCar < Car
100
+ end
101
+
76
102
  def create_event(options={})
77
103
  CIA::Event.create!({:source => Car.create!, :actor => User.create!, :action => "update"}.merge(options))
78
104
  end
metadata CHANGED
@@ -1,15 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cia
3
3
  version: !ruby/object:Gem::Version
4
+ version: 0.4.0
4
5
  prerelease:
5
- version: 0.3.7
6
6
  platform: ruby
7
7
  authors:
8
8
  - Michael Grosser
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-12-20 00:00:00.000000000 Z
12
+ date: 2013-01-10 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description:
15
15
  email: michael@grosser.it
@@ -46,23 +46,23 @@ rdoc_options: []
46
46
  require_paths:
47
47
  - lib
48
48
  required_ruby_version: !ruby/object:Gem::Requirement
49
+ none: false
49
50
  requirements:
50
51
  - - ! '>='
51
52
  - !ruby/object:Gem::Version
52
53
  version: '0'
53
54
  segments:
54
55
  - 0
55
- hash: 933978664134993553
56
- none: false
56
+ hash: 2880596585810436598
57
57
  required_rubygems_version: !ruby/object:Gem::Requirement
58
+ none: false
58
59
  requirements:
59
60
  - - ! '>='
60
61
  - !ruby/object:Gem::Version
61
62
  version: '0'
62
63
  segments:
63
64
  - 0
64
- hash: 933978664134993553
65
- none: false
65
+ hash: 2880596585810436598
66
66
  requirements: []
67
67
  rubyforge_project:
68
68
  rubygems_version: 1.8.24