appstats 0.20.12 → 0.21.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -6,6 +6,6 @@ doc
6
6
  config/appstats.yml
7
7
  config/initializers/appstats.rb
8
8
  log
9
- appstats_2010-09-21.log
9
+ appstats_*.log
10
10
  tmp
11
11
  .rvmrc
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- appstats (0.20.12)
4
+ appstats (0.21.1)
5
5
  daemons
6
6
  net-scp
7
7
  rails (>= 2.3.0)
data/Gemfile.lock.rails2 CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- appstats (0.20.12)
4
+ appstats (0.21.1)
5
5
  daemons
6
6
  net-scp
7
7
  rails (>= 2.3.0)
@@ -0,0 +1,22 @@
1
+ class CreateAudits < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :appstats_audits do |t|
4
+ t.string :table_name
5
+ t.string :column_type
6
+ t.string :obj_name
7
+ t.string :obj_attr
8
+ t.string :obj_type
9
+ t.integer :obj_id
10
+ t.string :action
11
+ t.string :old_value
12
+ t.string :new_value
13
+ t.text :old_value_full
14
+ t.text :new_value_full
15
+ t.timestamps
16
+ end
17
+ end
18
+
19
+ def self.down
20
+ drop_table :appstats_audits
21
+ end
22
+ end
@@ -0,0 +1,16 @@
1
+ class AddTestObjectColumns < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :appstats_test_objects, :last_name, :string
4
+ [:binary,:boolean,:date,:datetime,:decimal,:float,:integer,:string,:text,:time,:timestamp].each do |type|
5
+ add_column :appstats_test_objects, "blah_#{type}", type
6
+ end
7
+ end
8
+
9
+ def self.down
10
+ remove_column :appstats_test_objects, :last_name
11
+ [:binary,:boolean,:date,:datetime,:decimal,:float,:integer,:string,:text,:time,:timestamp].each do |type|
12
+ remove_column :appstats_test_objects, "blah_#{type}"
13
+ end
14
+ end
15
+
16
+ end
data/db/schema.rb CHANGED
@@ -10,7 +10,7 @@
10
10
  #
11
11
  # It's strongly recommended to check this file into your version control system.
12
12
 
13
- ActiveRecord::Schema.define(:version => 20110330171745) do
13
+ ActiveRecord::Schema.define(:version => 20110510173343) do
14
14
 
15
15
  create_table "appstats_action_context_keys", :force => true do |t|
16
16
  t.string "action_name"
@@ -28,6 +28,22 @@ ActiveRecord::Schema.define(:version => 20110330171745) do
28
28
  t.datetime "updated_at"
29
29
  end
30
30
 
31
+ create_table "appstats_audits", :force => true do |t|
32
+ t.string "table_name"
33
+ t.string "column_type"
34
+ t.string "obj_name"
35
+ t.string "obj_attr"
36
+ t.string "obj_type"
37
+ t.integer "obj_id"
38
+ t.string "action"
39
+ t.string "old_value"
40
+ t.string "new_value"
41
+ t.text "old_value_full"
42
+ t.text "new_value_full"
43
+ t.datetime "created_at"
44
+ t.datetime "updated_at"
45
+ end
46
+
31
47
  create_table "appstats_context_keys", :force => true do |t|
32
48
  t.string "name"
33
49
  t.string "status"
@@ -159,6 +175,18 @@ ActiveRecord::Schema.define(:version => 20110330171745) do
159
175
  t.string "name"
160
176
  t.datetime "created_at"
161
177
  t.datetime "updated_at"
178
+ t.string "last_name"
179
+ t.binary "blah_binary"
180
+ t.boolean "blah_boolean"
181
+ t.date "blah_date"
182
+ t.datetime "blah_datetime"
183
+ t.decimal "blah_decimal", :precision => 10, :scale => 0
184
+ t.float "blah_float"
185
+ t.integer "blah_integer"
186
+ t.string "blah_string"
187
+ t.text "blah_text"
188
+ t.time "blah_time"
189
+ t.datetime "blah_timestamp"
162
190
  end
163
191
 
164
192
  end
data/lib/appstats.rb CHANGED
@@ -1,8 +1,10 @@
1
1
  require 'rubygems'
2
2
  require 'active_record'
3
3
  require "#{File.dirname(__FILE__)}/appstats/acts_as_appstatsable"
4
+ require "#{File.dirname(__FILE__)}/appstats/acts_as_auditable"
4
5
  require "#{File.dirname(__FILE__)}/appstats/code_injections"
5
6
  require "#{File.dirname(__FILE__)}/appstats/entry"
7
+ require "#{File.dirname(__FILE__)}/appstats/audit"
6
8
  require "#{File.dirname(__FILE__)}/appstats/entry_date"
7
9
  require "#{File.dirname(__FILE__)}/appstats/date_range"
8
10
  require "#{File.dirname(__FILE__)}/appstats/action"
@@ -18,7 +18,6 @@ module ActsAsAppstatsable
18
18
  EOV
19
19
 
20
20
  acts_as_appstatsable_options(options)
21
-
22
21
  end
23
22
 
24
23
  def acts_as_appstatsable_options(options = {})
@@ -0,0 +1,45 @@
1
+ module ActsAsAuditable
2
+
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+ end
6
+
7
+ module ClassMethods
8
+
9
+ def acts_as_auditable(options = {})
10
+ self.cattr_accessor :auditable_options
11
+
12
+ class_eval <<-EOV
13
+ include ActsAsAuditable::InstanceMethods
14
+
15
+ after_create :audit_create
16
+ after_destroy :audit_destroy
17
+ after_update :audit_update
18
+ EOV
19
+
20
+ acts_as_auditable_options(options)
21
+ end
22
+
23
+ def acts_as_auditable_options(options = {})
24
+ self.auditable_options = options
25
+ end
26
+ end
27
+
28
+ module InstanceMethods
29
+
30
+ def audit_create
31
+ Appstats::Audit.audit_create(self,self.class.auditable_options)
32
+ end
33
+
34
+ def audit_destroy
35
+ Appstats::Audit.audit_destroy(self,self.class.auditable_options)
36
+ end
37
+
38
+ def audit_update
39
+ Appstats::Audit.audit_update(self,self.class.auditable_options)
40
+ end
41
+
42
+ end
43
+ end
44
+
45
+ ActiveRecord::Base.class_eval { include ActsAsAuditable }
@@ -0,0 +1,60 @@
1
+
2
+ module Appstats
3
+ class Audit < ActiveRecord::Base
4
+ set_table_name "appstats_audits"
5
+
6
+ attr_accessible :table_name, :column_type, :obj_name, :obj_attr, :obj_type, :obj_id, :action, :old_value, :new_value, :old_value_full, :new_value_full
7
+
8
+
9
+ def self.audit_create(obj, options = {})
10
+ count = 0
11
+ return count if obj.nil?
12
+ table_name = obj.class.table_name
13
+ obj_name = obj.class.name
14
+
15
+ count += save_audit(obj, { :action => "created"}, options)
16
+ obj.attributes.each do |obj_attr,new_value|
17
+ next if new_value.nil?
18
+ old_value = nil
19
+ count += save_audit(obj, { :action => "created", :obj_attr => obj_attr, :old_value => old_value, :new_value => new_value }, options)
20
+ end
21
+ count
22
+ end
23
+
24
+ def self.audit_update(obj, options = {})
25
+ count = 0
26
+ return count if obj.nil?
27
+
28
+ obj.changed_attributes.each do |obj_attr,old_value|
29
+ new_value = obj.send("#{obj_attr}")
30
+ count += save_audit(obj, { :action => "updated", :obj_attr => obj_attr, :old_value => old_value, :new_value => new_value}, options)
31
+ end
32
+ count
33
+ end
34
+
35
+ def self.audit_destroy(obj, options = {})
36
+ count = save_audit(obj, { :action => "destroyed" }, options)
37
+ count
38
+ end
39
+
40
+ private
41
+
42
+ def self.save_audit(obj,custom_fields,options = {})
43
+ return 0 if obj.nil?
44
+
45
+ if custom_fields.key?(:obj_attr)
46
+ obj_attr = custom_fields[:obj_attr]
47
+ return 0 if (options.key?(:except) && options[:except].include?(obj_attr.to_sym))
48
+ return 0 if (options.key?(:only) && !options[:only].include?(obj_attr.to_sym))
49
+ end
50
+
51
+ column_type = custom_fields.key?(:obj_attr) ? obj.class.columns_hash[custom_fields[:obj_attr]].sql_type : nil
52
+ obj_type = custom_fields.key?(:obj_attr) ? obj.class.columns_hash[custom_fields[:obj_attr]].type : nil
53
+ default_fields = { :table_name => obj.class.table_name, :column_type => column_type, :obj_type => obj_type, :obj_name => obj.class.name, :obj_id => obj.id, :old_value_full => custom_fields[:old_value], :new_value_full => custom_fields[:new_value] }
54
+ Audit.create(default_fields.merge(custom_fields))
55
+ 1
56
+ end
57
+
58
+
59
+ end
60
+ end
@@ -2,8 +2,15 @@ module Appstats
2
2
  class TestObject < ActiveRecord::Base
3
3
  set_table_name "appstats_test_objects"
4
4
  acts_as_appstatsable
5
+ acts_as_auditable
5
6
 
6
- attr_accessible :name
7
+ attr_accessible :name, :last_name
8
+
9
+ # after_save :blah
10
+ #
11
+ # def blah
12
+ # puts "#{changed_attributes.inspect}"
13
+ # end
7
14
 
8
15
  def to_s
9
16
  return "NILL" if name.nil?
@@ -1,3 +1,3 @@
1
1
  module Appstats
2
- VERSION = "0.20.12"
2
+ VERSION = "0.21.1"
3
3
  end
@@ -0,0 +1,102 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActsAsAuditable do
4
+
5
+ before(:each) do
6
+ Time.stub!(:now).and_return(Time.parse('2010-09-21 23:15:20'))
7
+ Appstats::TestObject.acts_as_auditable_options
8
+ Appstats::Audit.delete_all
9
+ end
10
+
11
+ after(:all) do
12
+ Appstats::TestObject.acts_as_auditable_options
13
+ end
14
+
15
+ describe "should be settable in the options" do
16
+
17
+ describe "create" do
18
+
19
+ it "should only track included options" do
20
+ Appstats::TestObject.acts_as_auditable_options(:only => [:name])
21
+ @obj = Appstats::TestObject.create(:name => "x")
22
+ Appstats::Audit.count.should == 2
23
+ end
24
+
25
+ it "should exclude track excluded options" do
26
+ Appstats::TestObject.acts_as_auditable_options(:except => [:name])
27
+ @obj = Appstats::TestObject.create(:name => "x")
28
+ Appstats::Audit.count.should == 4
29
+ end
30
+
31
+ it "should default to all " do
32
+ Appstats::TestObject.acts_as_auditable_options
33
+ @obj = Appstats::TestObject.create(:name => "x")
34
+ Appstats::Audit.count.should == 5
35
+ end
36
+
37
+ end
38
+
39
+ describe "update" do
40
+
41
+ before(:each) do
42
+ @obj = Appstats::TestObject.create(:name => "x")
43
+ Appstats::Audit.delete_all
44
+ @obj.name = "y"
45
+ @obj.last_name = "z"
46
+ @obj.blah_string = "x"
47
+ end
48
+
49
+ it "should only track included options" do
50
+ Appstats::TestObject.acts_as_auditable_options(:only => [:name])
51
+ @obj.save
52
+ Appstats::Audit.count.should == 1
53
+ end
54
+
55
+ it "should exclude track excluded options" do
56
+ Appstats::TestObject.acts_as_auditable_options(:except => [:name])
57
+ @obj.save
58
+ Appstats::Audit.count.should == 2
59
+ end
60
+
61
+ it "should default to all " do
62
+ @obj.save
63
+ Appstats::Audit.count.should == 3
64
+ end
65
+
66
+ end
67
+
68
+ end
69
+
70
+
71
+ # describe "default behaviour" do
72
+ #
73
+ # it "should track after_save" do
74
+ # @obj = Appstats::TestObject.create(:name => "x")
75
+ # Appstats::Logger.raw_read.last.should == Appstats::Logger.entry_to_s("object-created", :class_name => "Appstats::TestObject", :class_id => @obj.id, :details => "[x]")
76
+ # end
77
+ #
78
+ # it "should track after_destroy" do
79
+ # Appstats::TestObject.acts_as_auditable(:only => [:destroy])
80
+ # @obj = Appstats::TestObject.create(:name => "x")
81
+ # @obj.destroy
82
+ # Appstats::Logger.raw_read.last.should == Appstats::Logger.entry_to_s("object-destroyed", :class_name => "Appstats::TestObject", :class_id => @obj.id, :details => "[x]")
83
+ # end
84
+ #
85
+ # it "should track after_update" do
86
+ # Appstats::TestObject.acts_as_auditable(:only => [:update])
87
+ # @obj = Appstats::TestObject.create(:name => "x")
88
+ # @obj.name = "y"
89
+ # @obj.save
90
+ # Appstats::Logger.raw_read.last.should == Appstats::Logger.entry_to_s("object-updated", :class_name => "Appstats::TestObject", :class_id => @obj.id, :details => "[y]")
91
+ # end
92
+ #
93
+ #
94
+ # it "should handle exceptions" do
95
+ # @cheating = Appstats::TestObject.create(:name => "y")
96
+ # Appstats::Logger.stub!(:entry).with("object-created", :class_name => "Appstats::TestObject", :class_id => @cheating.id + 1, :details => "[x]").and_raise("something bad")
97
+ # @obj = Appstats::TestObject.create(:name => "x")
98
+ # Appstats::Logger.raw_read.last.should == Appstats::Logger.entry_to_s("appstats-exception", :on => "object-created", :error => "something bad")
99
+ # end
100
+ # end
101
+
102
+ end
@@ -0,0 +1,354 @@
1
+ require 'spec_helper'
2
+
3
+ module Appstats
4
+ describe Audit do
5
+
6
+ before(:each) do
7
+ Appstats::Audit.delete_all
8
+ @audit = Appstats::Audit.new
9
+ end
10
+
11
+ describe "#initialize" do
12
+
13
+ it "should set info to nil" do
14
+ @audit.table_name.should == nil
15
+ @audit.column_type.should == nil
16
+ @audit.obj_name.should == nil
17
+ @audit.obj_attr.should == nil
18
+ @audit.obj_type.should == nil
19
+ @audit.obj_id.should == nil
20
+ @audit.action.should == nil
21
+ @audit.old_value.should == nil
22
+ @audit.new_value.should == nil
23
+ @audit.old_value_full.should == nil
24
+ @audit.new_value_full.should == nil
25
+ end
26
+
27
+ it "should set on constructor" do
28
+ audit = Appstats::Audit.new(:table_name => 'a', :column_type => 'aa', :obj_name => 'c', :obj_attr => 'd', :obj_type => 'dd', :obj_id => 99, :action => 'x', :old_value => 'e', :new_value => 'f', :old_value_full => 'g', :new_value_full => 'h')
29
+ audit.table_name.should == 'a'
30
+ audit.column_type.should == 'aa'
31
+ audit.obj_name.should == 'c'
32
+ audit.obj_attr.should == 'd'
33
+ audit.obj_type.should == 'dd'
34
+ audit.obj_id.should == 99
35
+ audit.action.should == 'x'
36
+ audit.old_value.should == 'e'
37
+ audit.new_value.should == 'f'
38
+ audit.old_value_full.should == 'g'
39
+ audit.new_value_full.should == 'h'
40
+ end
41
+
42
+ end
43
+
44
+ describe "save a new object" do
45
+
46
+ it "should call audit_create" do
47
+ t = TestObject.new(:name => 'a')
48
+ Audit.should_receive(:audit_create).with(t,{}).and_return(5)
49
+ t.save.should == true
50
+ end
51
+
52
+ end
53
+
54
+ describe "update an existing object" do
55
+
56
+ it "should call audit_update" do
57
+ t = TestObject.create(:name => 'a')
58
+ t.name = "x"
59
+ Audit.should_receive(:audit_update).with(t,{}).and_return(2)
60
+ t.save
61
+ end
62
+
63
+ it "should store the type" do
64
+ t = TestObject.new
65
+
66
+ t.blah_binary = "b"
67
+ t.blah_boolean = true
68
+ t.blah_date = Date.parse("2011-09-21")
69
+ t.blah_datetime = DateTime.parse("2011-09-21 10:11:12")
70
+ t.blah_decimal = 10.11
71
+ t.blah_float = 0.33
72
+ t.blah_integer = 10
73
+ t.blah_string = "sss"
74
+ t.blah_text = "moresss"
75
+ t.blah_time = Time.parse("10:11:12")
76
+ t.blah_timestamp = Time.parse("10:11:12").to_i
77
+
78
+ t.save.should == true
79
+
80
+
81
+ Audit.count.should == 15
82
+
83
+ all = Audit.all
84
+ all[0].column_type.should == nil
85
+ all[0].obj_type.should == nil
86
+
87
+ all[1].obj_attr.should == "blah_string"
88
+ all[1].column_type.should == "varchar(255)"
89
+ all[1].obj_type.should == "string"
90
+
91
+ all[2].obj_attr.should == "created_at"
92
+ all[2].column_type.should == "datetime"
93
+ all[2].obj_type.should == "datetime"
94
+
95
+ all[3].obj_attr.should == "blah_timestamp"
96
+ all[3].column_type.should == "datetime"
97
+ all[3].obj_type.should == "datetime"
98
+
99
+ all[4].obj_attr.should == "updated_at"
100
+ all[4].column_type.should == "datetime"
101
+ all[4].obj_type.should == "datetime"
102
+
103
+ all[5].obj_attr.should == "id"
104
+ all[5].column_type.should == "int(11)"
105
+ all[5].obj_type.should == "integer"
106
+
107
+ all[6].obj_attr.should == "blah_decimal"
108
+ all[6].column_type.should == "decimal(10,0)"
109
+ all[6].obj_type.should == "integer"
110
+
111
+ all[7].obj_attr.should == "blah_boolean"
112
+ all[7].column_type.should == "tinyint(1)"
113
+ all[7].obj_type.should == "boolean"
114
+
115
+ all[8].obj_attr.should == "blah_binary"
116
+ all[8].column_type.should == "blob"
117
+ all[8].obj_type.should == "binary"
118
+
119
+ all[9].obj_attr.should == "blah_time"
120
+ all[9].column_type.should == "time"
121
+ all[9].obj_type.should == "time"
122
+
123
+ all[10].obj_attr.should == "blah_text"
124
+ all[10].column_type.should == "text"
125
+ all[10].obj_type.should == "text"
126
+
127
+ all[11].obj_attr.should == "blah_integer"
128
+ all[11].column_type.should == "int(11)"
129
+ all[11].obj_type.should == "integer"
130
+ end
131
+
132
+ end
133
+
134
+ describe "destroy an object" do
135
+
136
+ it "should call audit_destroy" do
137
+ t = TestObject.create(:name => 'a')
138
+ Audit.should_receive(:audit_destroy).with(t,{}).and_return(2)
139
+ t.destroy
140
+ end
141
+
142
+ end
143
+
144
+
145
+ describe "#audit_destroy" do
146
+
147
+ it "should ignore nil" do
148
+ Audit.audit_destroy(nil).should == 0
149
+ Audit.count.should == 0
150
+ end
151
+
152
+ it "should track changed and initialized attributes" do
153
+ t = TestObject.create(:name => 'a')
154
+ Audit.delete_all
155
+
156
+ Audit.audit_destroy(t).should == 1
157
+
158
+ all = Audit.all
159
+ audit = all[0]
160
+ audit.table_name.should == "appstats_test_objects"
161
+ audit.column_type.should == nil
162
+ audit.obj_name.should == "Appstats::TestObject"
163
+ audit.obj_attr.should == nil
164
+ audit.obj_id.should == t.id
165
+ audit.action.should == "destroyed"
166
+ audit.old_value.should == nil
167
+ audit.new_value.should == nil
168
+ audit.old_value_full.should == nil
169
+ audit.new_value_full.should == nil
170
+ end
171
+
172
+ it "should do the same on :except" do
173
+ t = TestObject.create(:name => 'a')
174
+ Audit.delete_all
175
+ Audit.audit_destroy(t, :except => [:name]).should == 1
176
+ end
177
+
178
+ it "should do the same on :only" do
179
+ t = TestObject.create(:name => 'a')
180
+ Audit.delete_all
181
+ Audit.audit_destroy(t, :only => [:name]).should == 1
182
+ end
183
+
184
+ end
185
+
186
+ describe "#audit_update" do
187
+
188
+ it "should ignore nil" do
189
+ Audit.audit_update(nil).should == 0
190
+ Audit.count.should == 0
191
+ end
192
+
193
+ it "should be filterable on :except" do
194
+ t = TestObject.create(:name => 'a')
195
+ Audit.delete_all
196
+
197
+ t.name = 'b'
198
+ t.last_name = 'c'
199
+ Audit.audit_update(t, :except => [:name]).should == 1
200
+
201
+ all = Audit.all
202
+ audit = all[0]
203
+ audit.table_name.should == "appstats_test_objects"
204
+ audit.column_type.should == "varchar(255)"
205
+ audit.obj_name.should == "Appstats::TestObject"
206
+ audit.obj_attr.should == 'last_name'
207
+ end
208
+
209
+ it "should be filterable on :only" do
210
+ t = TestObject.create(:name => 'a')
211
+ Audit.delete_all
212
+
213
+ t.name = 'b'
214
+ t.last_name = 'c'
215
+ Audit.audit_update(t, :only => [:name]).should == 1
216
+
217
+ all = Audit.all
218
+ audit = all[0]
219
+ audit.table_name.should == "appstats_test_objects"
220
+ audit.column_type.should == "varchar(255)"
221
+ audit.obj_name.should == "Appstats::TestObject"
222
+ audit.obj_attr.should == 'name'
223
+ end
224
+
225
+ it "should track changed and initialized attributes" do
226
+ t = TestObject.create(:name => 'a')
227
+ Audit.delete_all
228
+
229
+ t.name = 'b'
230
+ t.last_name = 'c'
231
+ Audit.audit_update(t).should == 2
232
+
233
+ all = Audit.all
234
+ audit = all[0]
235
+ audit.table_name.should == "appstats_test_objects"
236
+ audit.column_type.should == "varchar(255)"
237
+ audit.obj_name.should == "Appstats::TestObject"
238
+ audit.obj_attr.should == 'name'
239
+ audit.obj_id.should == t.id
240
+ audit.action.should == "updated"
241
+ audit.old_value.should == 'a'
242
+ audit.new_value.should == 'b'
243
+ audit.old_value_full.should == 'a'
244
+ audit.new_value_full.should == 'b'
245
+
246
+ audit = all[1]
247
+ audit.table_name.should == "appstats_test_objects"
248
+ audit.column_type.should == "varchar(255)"
249
+ audit.obj_name.should == "Appstats::TestObject"
250
+ audit.obj_attr.should == 'last_name'
251
+ audit.obj_id.should == t.id
252
+ audit.action.should == "updated"
253
+ audit.old_value.should == nil
254
+ audit.new_value.should == 'c'
255
+ audit.old_value_full.should == nil
256
+ audit.new_value_full.should == 'c'
257
+
258
+ end
259
+
260
+
261
+ end
262
+
263
+ describe "#audit_create" do
264
+
265
+ it "should ignore nil" do
266
+ Audit.audit_create(nil).should == 0
267
+ Audit.count.should == 0
268
+ end
269
+
270
+ it "should be filterable on :except" do
271
+ t = TestObject.create(:name => 'a')
272
+ Audit.delete_all
273
+
274
+ Audit.audit_create(t, :except => [:name]).should == 4
275
+ Audit.count.should == 4
276
+ end
277
+
278
+ it "should be filterable on :only" do
279
+ t = TestObject.create(:name => 'a')
280
+ Audit.delete_all
281
+
282
+ Audit.audit_create(t, :only => [:name]).should == 2
283
+ Audit.count.should == 2
284
+
285
+ all = Audit.all
286
+ audit = all[0]
287
+ audit.table_name.should == "appstats_test_objects"
288
+ audit.obj_name.should == "Appstats::TestObject"
289
+ audit.obj_attr.should == nil
290
+
291
+ audit = all[1]
292
+ audit.table_name.should == "appstats_test_objects"
293
+ audit.obj_name.should == "Appstats::TestObject"
294
+ audit.obj_attr.should == 'name'
295
+ end
296
+
297
+ it "should store all non nil properties on create" do
298
+ t = TestObject.create(:name => 'a')
299
+ Audit.delete_all
300
+
301
+ Audit.audit_create(t).should == 5
302
+ Audit.count.should == 5
303
+
304
+ all = Audit.all
305
+ audit = all[0]
306
+ audit.table_name.should == "appstats_test_objects"
307
+ audit.obj_name.should == "Appstats::TestObject"
308
+ audit.obj_attr.should == nil
309
+ audit.obj_id.should == t.id
310
+ audit.action.should == "created"
311
+ audit.old_value.should == nil
312
+ audit.new_value.should == nil
313
+ audit.old_value_full.should == nil
314
+ audit.new_value_full.should == nil
315
+
316
+ audit = all[1]
317
+ audit.table_name.should == "appstats_test_objects"
318
+ audit.obj_name.should == "Appstats::TestObject"
319
+ audit.obj_attr.should == 'name'
320
+ audit.obj_id.should == t.id
321
+ audit.action.should == "created"
322
+ audit.old_value.should == nil
323
+ audit.new_value.should == 'a'
324
+ audit.old_value_full.should == nil
325
+ audit.new_value_full.should == 'a'
326
+
327
+ audit = all[2]
328
+ audit.table_name.should == "appstats_test_objects"
329
+ audit.obj_name.should == "Appstats::TestObject"
330
+ audit.obj_attr.should == 'created_at'
331
+ audit.obj_id.should == t.id
332
+ audit.action.should == "created"
333
+ audit.old_value.should == nil
334
+ audit.new_value.should == t.created_at.strftime("%Y-%m-%d %H:%M:%S")
335
+ audit.old_value_full.should == nil
336
+ audit.new_value_full.should == t.created_at.strftime("%Y-%m-%d %H:%M:%S")
337
+
338
+ audit = all[3]
339
+ audit.table_name.should == "appstats_test_objects"
340
+ audit.obj_name.should == "Appstats::TestObject"
341
+ audit.obj_attr.should == 'updated_at'
342
+ audit.obj_id.should == t.id
343
+ audit.action.should == "created"
344
+ audit.old_value.should == nil
345
+ audit.new_value.should == t.created_at.strftime("%Y-%m-%d %H:%M:%S")
346
+ audit.old_value_full.should == nil
347
+ audit.new_value_full.should == t.created_at.strftime("%Y-%m-%d %H:%M:%S")
348
+ end
349
+
350
+ end
351
+
352
+
353
+ end
354
+ end
data/spec/entry_spec.rb CHANGED
@@ -193,18 +193,18 @@ module Appstats
193
193
  end
194
194
 
195
195
  it "should understand an entry without contexts" do
196
- entry = Entry.create_from_logger_string("0.20.12 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search")
196
+ entry = Entry.create_from_logger_string("0.21.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search")
197
197
  Entry.count.should == @before_count + 1
198
198
  entry.action.should == "address_search"
199
- entry.raw_entry.should == "0.20.12 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search"
199
+ entry.raw_entry.should == "0.21.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search"
200
200
  entry.occurred_at.should == Time.parse("2010-09-21 23:15:20")
201
201
  end
202
202
 
203
203
  it "should understand contexts" do
204
- entry = Entry.create_from_logger_string("0.20.12 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live")
204
+ entry = Entry.create_from_logger_string("0.21.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live")
205
205
  Entry.count.should == @before_count + 1
206
206
  entry.action.should == "address_filter"
207
- entry.raw_entry.should == "0.20.12 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live"
207
+ entry.raw_entry.should == "0.21.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live"
208
208
  entry.occurred_at.should == Time.parse("2010-09-21 23:15:20")
209
209
  entry.contexts.size.should == 2
210
210
  entry.contexts[0].context_key = "app_name"
@@ -214,10 +214,10 @@ module Appstats
214
214
  end
215
215
 
216
216
  it "should handle 'action' as a context" do
217
- entry = Entry.create_from_logger_string('0.20.12 setup[:,=,-n] 2011-02-24 12:59:57 action=page-view : action=save_ovcen : app_name=cdb')
217
+ entry = Entry.create_from_logger_string('0.21.1 setup[:,=,-n] 2011-02-24 12:59:57 action=page-view : action=save_ovcen : app_name=cdb')
218
218
  Entry.count.should == @before_count + 1
219
219
  entry.action.should == "page-view"
220
- entry.raw_entry.should == "0.20.12 setup[:,=,-n] 2011-02-24 12:59:57 action=page-view : action=save_ovcen : app_name=cdb"
220
+ entry.raw_entry.should == "0.21.1 setup[:,=,-n] 2011-02-24 12:59:57 action=page-view : action=save_ovcen : app_name=cdb"
221
221
  entry.occurred_at.should == Time.parse("2011-02-24 12:59:57")
222
222
  entry.contexts.size.should == 2
223
223
  entry.contexts[0].context_key = "action"
@@ -228,10 +228,10 @@ module Appstats
228
228
  end
229
229
 
230
230
  it "should handle multiple of the same 'context'" do
231
- entry = Entry.create_from_logger_string('0.20.12 setup[:,=,-n] 2011-02-24 12:59:57 action=page-view : app_name=market : app_name=cdb')
231
+ entry = Entry.create_from_logger_string('0.21.1 setup[:,=,-n] 2011-02-24 12:59:57 action=page-view : app_name=market : app_name=cdb')
232
232
  Entry.count.should == @before_count + 1
233
233
  entry.action.should == "page-view"
234
- entry.raw_entry.should == "0.20.12 setup[:,=,-n] 2011-02-24 12:59:57 action=page-view : app_name=market : app_name=cdb"
234
+ entry.raw_entry.should == "0.21.1 setup[:,=,-n] 2011-02-24 12:59:57 action=page-view : app_name=market : app_name=cdb"
235
235
  entry.occurred_at.should == Time.parse("2011-02-24 12:59:57")
236
236
  entry.contexts.size.should == 2
237
237
  entry.contexts[0].context_key = "app_name"
data/spec/logger_spec.rb CHANGED
@@ -122,12 +122,12 @@ module Appstats
122
122
 
123
123
  it "should accept numbers" do
124
124
  Appstats::Logger.entry(5, :blah => 6)
125
- Appstats::Logger.raw_read.should == ["0.20.12 setup[:,=,-n] 2010-09-21 23:15:20 action=5 : blah=6"]
125
+ Appstats::Logger.raw_read.should == ["0.21.1 setup[:,=,-n] 2010-09-21 23:15:20 action=5 : blah=6"]
126
126
  end
127
127
 
128
128
  it "should accept arrays" do
129
129
  Appstats::Logger.entry('search', :provider => [ 'one', 'two' ])
130
- Appstats::Logger.raw_read.should == ["0.20.12 setup[:,=,-n] 2010-09-21 23:15:20 action=search : provider=one : provider=two"]
130
+ Appstats::Logger.raw_read.should == ["0.21.1 setup[:,=,-n] 2010-09-21 23:15:20 action=search : provider=one : provider=two"]
131
131
  end
132
132
 
133
133
 
@@ -137,7 +137,7 @@ module Appstats
137
137
 
138
138
  it "should look similar to regular entry" do
139
139
  Appstats::Logger.exception_entry(RuntimeError.new("blah"),:on => "login")
140
- Appstats::Logger.raw_read.should == ["0.20.12 setup[:,=,-n] 2010-09-21 23:15:20 action=appstats-exception : error=blah : on=login"]
140
+ Appstats::Logger.raw_read.should == ["0.21.1 setup[:,=,-n] 2010-09-21 23:15:20 action=appstats-exception : error=blah : on=login"]
141
141
  end
142
142
 
143
143
  end
@@ -154,47 +154,47 @@ module Appstats
154
154
 
155
155
  it "should handle a statistics entry" do
156
156
  expected = { :action => "address_search", :timestamp => "2010-09-21 23:15:20" }
157
- actual = Appstats::Logger.entry_to_hash("0.20.12 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search")
157
+ actual = Appstats::Logger.entry_to_hash("0.21.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search")
158
158
  actual.should == expected
159
159
  end
160
160
 
161
161
  it "should handle contexts" do
162
162
  expected = { :action => "address_filter", :timestamp => "2010-09-21 23:15:20", :server => "Live", :app_name => 'Market' }
163
- actual = Appstats::Logger.entry_to_hash("0.20.12 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live")
163
+ actual = Appstats::Logger.entry_to_hash("0.21.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live")
164
164
  actual.should == expected
165
165
  end
166
166
 
167
167
  it "should handle multiple actions" do
168
168
  expected = { :action => ["address_filter", "blah"], :timestamp => "2010-09-21 23:15:20", :server => "Live", :app_name => 'Market' }
169
- actual = Appstats::Logger.entry_to_hash("0.20.12 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : action=blah : app_name=Market : server=Live")
169
+ actual = Appstats::Logger.entry_to_hash("0.21.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : action=blah : app_name=Market : server=Live")
170
170
  actual.should == expected
171
171
  end
172
172
 
173
173
  it "should handle multiple of same context" do
174
174
  expected = { :action => "address_filter", :timestamp => "2010-09-21 23:15:20", :server => "Live", :app_name => ['Sin','Market'] }
175
- actual = Appstats::Logger.entry_to_hash("0.20.12 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Sin : app_name=Market : server=Live")
175
+ actual = Appstats::Logger.entry_to_hash("0.21.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Sin : app_name=Market : server=Live")
176
176
  actual.should == expected
177
177
  end
178
178
 
179
179
  it "should handle no actions" do
180
180
  expected = { :action => "UNKNOWN_ACTION", :timestamp => "2010-09-21 23:15:20", :server => "Live", :app_name => 'Market' }
181
- actual = Appstats::Logger.entry_to_hash("0.20.12 setup[:,=,-n] 2010-09-21 23:15:20 app_name=Market : server=Live")
181
+ actual = Appstats::Logger.entry_to_hash("0.21.1 setup[:,=,-n] 2010-09-21 23:15:20 app_name=Market : server=Live")
182
182
  actual.should == expected
183
183
  end
184
184
 
185
185
  it "should handle actions with the delimiter (and change the delimiter)" do
186
186
  expected = { :action => "address:=search-n", :timestamp => "2010-09-21 23:15:20" }
187
- actual = Appstats::Logger.entry_to_hash("0.20.12 setup[::,==,--n] 2010-09-21 23:15:20 action==address:=search-n")
187
+ actual = Appstats::Logger.entry_to_hash("0.21.1 setup[::,==,--n] 2010-09-21 23:15:20 action==address:=search-n")
188
188
  actual.should == expected
189
189
 
190
190
  expected = { :action => "address::search==--n", :timestamp => "2010-09-21 23:15:20" }
191
- actual = Appstats::Logger.entry_to_hash("0.20.12 setup[:::,===,---n] 2010-09-21 23:15:20 action===address::search==--n")
191
+ actual = Appstats::Logger.entry_to_hash("0.21.1 setup[:::,===,---n] 2010-09-21 23:15:20 action===address::search==--n")
192
192
  actual.should == expected
193
193
  end
194
194
 
195
195
  it "should handle contexts with the delimiter (and change the delimiter)" do
196
196
  expected = { :action => "address", :timestamp => "2010-09-21 23:15:20", :server => "market:eval=-n" }
197
- actual = Appstats::Logger.entry_to_hash("0.20.12 setup[::,==,--n] 2010-09-21 23:15:20 action==address :: server==market:eval=-n")
197
+ actual = Appstats::Logger.entry_to_hash("0.21.1 setup[::,==,--n] 2010-09-21 23:15:20 action==address :: server==market:eval=-n")
198
198
  actual.should == expected
199
199
  end
200
200
 
@@ -203,66 +203,66 @@ module Appstats
203
203
  describe "#entry_to_s" do
204
204
 
205
205
  it "should handle a statistics entry" do
206
- expected = "0.20.12 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search"
206
+ expected = "0.21.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search"
207
207
  actual = Appstats::Logger.entry_to_s("address_search")
208
208
  actual.should == expected
209
209
  end
210
210
 
211
211
  it "should handle numbers" do
212
- expected = "0.20.12 setup[:,=,-n] 2010-09-21 23:15:20 action=1 : note=2.2"
212
+ expected = "0.21.1 setup[:,=,-n] 2010-09-21 23:15:20 action=1 : note=2.2"
213
213
  actual = Appstats::Logger.entry_to_s(1,:note => 2.2)
214
214
  actual.should == expected
215
215
  end
216
216
 
217
217
  it "should handle default contexts" do
218
218
  Appstats::Logger.default_contexts[:app_name] = "market"
219
- expected = "0.20.12 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search : app_name=market"
219
+ expected = "0.21.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search : app_name=market"
220
220
  actual = Appstats::Logger.entry_to_s("address_search")
221
221
  actual.should == expected
222
222
  end
223
223
 
224
224
  it "should handle contexts (and sort them by symbol)" do
225
- expected = "0.20.12 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live"
225
+ expected = "0.21.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_filter : app_name=Market : server=Live"
226
226
  actual = Appstats::Logger.entry_to_s("address_filter", { :server => "Live", :app_name => 'Market' })
227
227
  actual.should == expected
228
228
  end
229
229
 
230
230
  it "should handle actions with the delimiter (and change the delimiter)" do
231
- expected = "0.20.12 setup[::,==,--n] 2010-09-21 23:15:20 action==address:=search-n"
231
+ expected = "0.21.1 setup[::,==,--n] 2010-09-21 23:15:20 action==address:=search-n"
232
232
  actual = Appstats::Logger.entry_to_s("address:=search-n")
233
233
  actual.should == expected
234
234
 
235
- expected = "0.20.12 setup[:::,===,---n] 2010-09-21 23:15:20 action===address::search==--n"
235
+ expected = "0.21.1 setup[:::,===,---n] 2010-09-21 23:15:20 action===address::search==--n"
236
236
  actual = Appstats::Logger.entry_to_s("address::search==--n")
237
237
  actual.should == expected
238
238
  end
239
239
 
240
240
  it "should handle contexts with the delimiter (and change the delimiter)" do
241
- expected = "0.20.12 setup[::,==,--n] 2010-09-21 23:15:20 action==address :: server==market:eval=-n"
241
+ expected = "0.21.1 setup[::,==,--n] 2010-09-21 23:15:20 action==address :: server==market:eval=-n"
242
242
  actual = Appstats::Logger.entry_to_s("address", :server => 'market:eval=-n')
243
243
  actual.should == expected
244
244
  end
245
245
 
246
246
  it "should ignore spaces" do
247
- expected = "0.20.12 setup[:,=,-n] 2010-09-21 23:15:20 action=address search"
247
+ expected = "0.21.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address search"
248
248
  actual = Appstats::Logger.entry_to_s("address search")
249
249
  actual.should == expected
250
250
  end
251
251
 
252
252
  it "should convert newlines in action" do
253
- expected = "0.20.12 setup[:,=,-n] 2010-09-21 23:15:20 action=address_-nsearch"
253
+ expected = "0.21.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_-nsearch"
254
254
  actual = Appstats::Logger.entry_to_s("address_\nsearch")
255
255
  actual.should == expected
256
256
  end
257
257
 
258
258
  it "should convert newlines in context" do
259
- expected = "0.20.12 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search : blah=some-nlong-nstatement"
259
+ expected = "0.21.1 setup[:,=,-n] 2010-09-21 23:15:20 action=address_search : blah=some-nlong-nstatement"
260
260
  actual = Appstats::Logger.entry_to_s("address_search",:blah => "some\nlong\nstatement")
261
261
  actual.should == expected
262
262
  end
263
263
 
264
264
  it "should convert newlines based on the delimiter" do
265
- expected = "0.20.12 setup[::,==,--n] 2010-09-21 23:15:20 action==address:=--nsearch-n"
265
+ expected = "0.21.1 setup[::,==,--n] 2010-09-21 23:15:20 action==address:=--nsearch-n"
266
266
  actual = Appstats::Logger.entry_to_s("address:=\nsearch-n")
267
267
  actual.should == expected
268
268
  end
@@ -11,11 +11,13 @@ module Appstats
11
11
 
12
12
  it "should set name to nil" do
13
13
  @obj.name.should == nil
14
+ @obj.last_name.should == nil
14
15
  end
15
16
 
16
17
  it "should set on constructor" do
17
- obj = Appstats::TestObject.new(:name => 'a')
18
+ obj = Appstats::TestObject.new(:name => 'a', :last_name => 'b')
18
19
  obj.name.should == 'a'
20
+ obj.last_name.should == 'b'
19
21
  end
20
22
 
21
23
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: appstats
3
3
  version: !ruby/object:Gem::Version
4
- hash: 87
4
+ hash: 73
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 20
9
- - 12
10
- version: 0.20.12
8
+ - 21
9
+ - 1
10
+ version: 0.21.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Andrew Forward
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-04-20 00:00:00 -04:00
18
+ date: 2011-05-11 00:00:00 -04:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -182,12 +182,16 @@ files:
182
182
  - db/migrations/20110318203339_add_appstats_results_latest_flag.rb
183
183
  - db/migrations/20110321154125_add_appstats_results_query_duration_in_seconds.rb
184
184
  - db/migrations/20110330171745_create_appstats_action_contexts.rb
185
+ - db/migrations/20110510141236_create_audits.rb
186
+ - db/migrations/20110510173343_add_test_object_columns.rb
185
187
  - db/schema.rb
186
188
  - lib/appstats.rb
187
189
  - lib/appstats/action.rb
188
190
  - lib/appstats/action_context_key.rb
189
191
  - lib/appstats/acts_as_appstatsable.rb
192
+ - lib/appstats/acts_as_auditable.rb
190
193
  - lib/appstats/appstats_query.rb
194
+ - lib/appstats/audit.rb
191
195
  - lib/appstats/ci.rake
192
196
  - lib/appstats/code_injections.rb
193
197
  - lib/appstats/context.rb
@@ -233,8 +237,10 @@ files:
233
237
  - spec/action_context_key_spec.rb
234
238
  - spec/action_spec.rb
235
239
  - spec/acts_as_appstatsble_spec.rb
240
+ - spec/acts_as_auditable_spec.rb
236
241
  - spec/appstats_query_spec.rb
237
242
  - spec/appstats_spec.rb
243
+ - spec/audit_spec.rb
238
244
  - spec/context_key_spec.rb
239
245
  - spec/context_spec.rb
240
246
  - spec/context_value_spec.rb
@@ -290,8 +296,10 @@ test_files:
290
296
  - spec/action_context_key_spec.rb
291
297
  - spec/action_spec.rb
292
298
  - spec/acts_as_appstatsble_spec.rb
299
+ - spec/acts_as_auditable_spec.rb
293
300
  - spec/appstats_query_spec.rb
294
301
  - spec/appstats_spec.rb
302
+ - spec/audit_spec.rb
295
303
  - spec/context_key_spec.rb
296
304
  - spec/context_spec.rb
297
305
  - spec/context_value_spec.rb