appstats 0.20.12 → 0.21.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/.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