change_logger 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest +9 -0
- data/Rakefile +12 -1
- data/change_logger.gemspec +3 -3
- data/cucumber.yml.bac +8 -0
- data/features/log_changes.feature +48 -0
- data/features/step_definitions/log_changes_steps.rb +106 -0
- data/features/support/env.rb +19 -0
- data/features/support/hooks.rb +4 -0
- data/lib/change_logger/acts_as_change_logger.rb +21 -14
- data/lib/generators/templates/create_change_logs.rb +3 -2
- data/spec/factories.rb +10 -0
- data/spec/migrate/20101201_init_test_db.rb +32 -0
- data/spec/models/permission.rb +4 -0
- data/spec/models/user.rb +5 -0
- data.tar.gz.sig +1 -2
- metadata +12 -3
- metadata.gz.sig +0 -0
data/Manifest
CHANGED
@@ -3,6 +3,11 @@ MIT-LICENSE
|
|
3
3
|
Manifest
|
4
4
|
README
|
5
5
|
Rakefile
|
6
|
+
cucumber.yml.bac
|
7
|
+
features/log_changes.feature
|
8
|
+
features/step_definitions/log_changes_steps.rb
|
9
|
+
features/support/env.rb
|
10
|
+
features/support/hooks.rb
|
6
11
|
lib/app/models/change_log.rb
|
7
12
|
lib/change_logger.rb
|
8
13
|
lib/change_logger/acts_as_change_logger.rb
|
@@ -10,3 +15,7 @@ lib/change_logger/railtie.rb
|
|
10
15
|
lib/change_logger/whodunnit.rb
|
11
16
|
lib/generators/change_logger_generator.rb
|
12
17
|
lib/generators/templates/create_change_logs.rb
|
18
|
+
spec/factories.rb
|
19
|
+
spec/migrate/20101201_init_test_db.rb
|
20
|
+
spec/models/permission.rb
|
21
|
+
spec/models/user.rb
|
data/Rakefile
CHANGED
@@ -1,12 +1,23 @@
|
|
1
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__), 'features', 'support')
|
1
2
|
require 'rubygems'
|
2
3
|
require 'rake'
|
3
4
|
require 'echoe'
|
5
|
+
require 'env'
|
4
6
|
|
5
|
-
Echoe.new('change_logger', '0.0.
|
7
|
+
Echoe.new('change_logger', '0.0.3') do |p|
|
6
8
|
p.description = "A gem for tracking what changes and who did it"
|
7
9
|
p.url = "http://github.com/danengle/awesome_tables"
|
8
10
|
p.author = "Dan Engle"
|
9
11
|
p.email = "engle.68 @nospam@ gmail.com"
|
10
12
|
p.ignore_pattern = ["tmp/*", "script/*"]
|
11
13
|
p.development_dependencies = []
|
14
|
+
end
|
15
|
+
|
16
|
+
namespace :db do
|
17
|
+
desc "Migrate the test sqlite3 database"
|
18
|
+
task(:migrate) do
|
19
|
+
ActiveRecord::Base.logger = Logger.new(STDOUT)
|
20
|
+
ActiveRecord::Migration.verbose = true
|
21
|
+
ActiveRecord::Migrator.migrate("spec/migrate")
|
22
|
+
end
|
12
23
|
end
|
data/change_logger.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{change_logger}
|
5
|
-
s.version = "0.0.
|
5
|
+
s.version = "0.0.3"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Dan Engle"]
|
9
9
|
s.cert_chain = ["/Users/danengle/.ssh/gem-public_cert.pem"]
|
10
|
-
s.date = %q{2010-12-
|
10
|
+
s.date = %q{2010-12-05}
|
11
11
|
s.description = %q{A gem for tracking what changes and who did it}
|
12
12
|
s.email = %q{engle.68 @nospam@ gmail.com}
|
13
13
|
s.extra_rdoc_files = ["CHANGELOG", "README", "lib/app/models/change_log.rb", "lib/change_logger.rb", "lib/change_logger/acts_as_change_logger.rb", "lib/change_logger/railtie.rb", "lib/change_logger/whodunnit.rb", "lib/generators/change_logger_generator.rb", "lib/generators/templates/create_change_logs.rb"]
|
14
|
-
s.files = ["CHANGELOG", "MIT-LICENSE", "Manifest", "README", "Rakefile", "lib/app/models/change_log.rb", "lib/change_logger.rb", "lib/change_logger/acts_as_change_logger.rb", "lib/change_logger/railtie.rb", "lib/change_logger/whodunnit.rb", "lib/generators/change_logger_generator.rb", "lib/generators/templates/create_change_logs.rb", "change_logger.gemspec"]
|
14
|
+
s.files = ["CHANGELOG", "MIT-LICENSE", "Manifest", "README", "Rakefile", "cucumber.yml.bac", "features/log_changes.feature", "features/step_definitions/log_changes_steps.rb", "features/support/env.rb", "features/support/hooks.rb", "lib/app/models/change_log.rb", "lib/change_logger.rb", "lib/change_logger/acts_as_change_logger.rb", "lib/change_logger/railtie.rb", "lib/change_logger/whodunnit.rb", "lib/generators/change_logger_generator.rb", "lib/generators/templates/create_change_logs.rb", "spec/factories.rb", "spec/migrate/20101201_init_test_db.rb", "spec/models/permission.rb", "spec/models/user.rb", "change_logger.gemspec"]
|
15
15
|
s.homepage = %q{http://github.com/danengle/awesome_tables}
|
16
16
|
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Change_logger", "--main", "README"]
|
17
17
|
s.require_paths = ["lib"]
|
data/cucumber.yml.bac
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
<%
|
2
|
+
rerun = File.file?('rerun.txt') ? IO.read('rerun.txt') : ""
|
3
|
+
rerun_opts = rerun.to_s.strip.empty? ? "--format #{ENV['CUCUMBER_FORMAT'] || 'progress'} features" : "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} #{rerun}"
|
4
|
+
std_opts = "--format #{ENV['CUCUMBER_FORMAT'] || 'progress'} --strict --tags ~@wip"
|
5
|
+
%>
|
6
|
+
default: <%= std_opts %> features
|
7
|
+
wip: --tags @wip:3 --wip features
|
8
|
+
rerun: <%= rerun_opts %> --format rerun --out rerun.txt --strict --tags ~@wip
|
@@ -0,0 +1,48 @@
|
|
1
|
+
Feature: create a change log
|
2
|
+
As a user
|
3
|
+
I want to record changes to an object
|
4
|
+
So that I can track and revert changes if needed
|
5
|
+
|
6
|
+
Scenario: create an object
|
7
|
+
Given I am identified as "dan"
|
8
|
+
And User is an ActiveRecord model
|
9
|
+
And it is using acts_as_change_logger
|
10
|
+
When I initialize a new user
|
11
|
+
And I set the name to "bob"
|
12
|
+
And I save the user
|
13
|
+
Then there should be a change_log record created for name
|
14
|
+
And there should not be a change_log record for any ignored attributes
|
15
|
+
And there should not be a change_log for any blank attributes
|
16
|
+
|
17
|
+
Scenario: delete an object
|
18
|
+
Given I am identified as "dan"
|
19
|
+
And user is an ActiveRecord object
|
20
|
+
And it is using acts_as_change_logger
|
21
|
+
When I delete the user
|
22
|
+
Then there should be change_log records created for all unignored attributes
|
23
|
+
|
24
|
+
Scenario: update an object
|
25
|
+
Given I am identified as "dan"
|
26
|
+
And user is an ActiveRecord object
|
27
|
+
And it is using acts_as_change_logger
|
28
|
+
And users name is not "charlie"
|
29
|
+
When I update the name to "charlie"
|
30
|
+
Then there should be a change_log record created for name
|
31
|
+
|
32
|
+
Scenario: add an has_and_belongs_to_many association to an object
|
33
|
+
Given I am identified as "dan"
|
34
|
+
And user is an ActiveRecord object
|
35
|
+
And it is using acts_as_change_logger
|
36
|
+
And it has_and_belongs_to_many permissions
|
37
|
+
And user does not have the permission "admin"
|
38
|
+
When I add that permission to user
|
39
|
+
Then there should be an association add change_log record created
|
40
|
+
|
41
|
+
Scenario: remove a has_and_belongs_to_many association from an object
|
42
|
+
Given I am identified as "dan"
|
43
|
+
And user is an ActiveRecord object
|
44
|
+
And it is using acts_as_change_logger
|
45
|
+
And it has_and_belongs_to_many permissions
|
46
|
+
And user has the permission "admin"
|
47
|
+
When I remove that permission from user
|
48
|
+
Then there should be an association remove change_log record created
|
@@ -0,0 +1,106 @@
|
|
1
|
+
Given /^I am identified as "([^"]*)"$/ do |whodunnit| #"
|
2
|
+
(ChangeLogger.whodunnit = whodunnit).should be(whodunnit)
|
3
|
+
end
|
4
|
+
|
5
|
+
Given /^User is an ActiveRecord model$/ do
|
6
|
+
User.ancestors.include?(ActiveRecord::Base).should be_true
|
7
|
+
end
|
8
|
+
|
9
|
+
Given /^it is using acts_as_change_logger$/ do
|
10
|
+
User.ancestors.include?(ChangeLogger::ActsAsChangeLogger::InstanceMethods).should be_true
|
11
|
+
end
|
12
|
+
|
13
|
+
When /^I initialize a new user$/ do
|
14
|
+
@user = User.new
|
15
|
+
end
|
16
|
+
|
17
|
+
When /^I set the name to "([^"]*)"$/ do |name| #"
|
18
|
+
@user.name = name
|
19
|
+
@user.name.should == name
|
20
|
+
end
|
21
|
+
|
22
|
+
When /^I save the user$/ do
|
23
|
+
@user.save
|
24
|
+
end
|
25
|
+
|
26
|
+
Then /^there should be a change_log record created for ([^"]*)$/ do |name| #"
|
27
|
+
change_log = ChangeLog.where({:item_id => @user.id, :item_type => @user.class.to_s, :attribute_name => name}).first
|
28
|
+
change_log.should_not be_blank
|
29
|
+
change_log.old_value.should == ChangeLogger::ActsAsChangeLogger::ACTIONS[:create]
|
30
|
+
change_log.new_value.should == @user.name
|
31
|
+
end
|
32
|
+
|
33
|
+
Then /^there should not be a change_log record for any ignored attributes$/ do
|
34
|
+
change_logs = ChangeLog.where({:item_id => @user.id, :item_type => @user.class.to_s})
|
35
|
+
change_logs.size.should == 1
|
36
|
+
end
|
37
|
+
|
38
|
+
Given /^user is an ActiveRecord object$/ do
|
39
|
+
@user = Factory.create(:user)
|
40
|
+
end
|
41
|
+
|
42
|
+
Given /^it has_and_belongs_to_many permissions$/ do
|
43
|
+
@user.class.reflect_on_all_associations(:has_and_belongs_to_many).any?{|a| a.name == :permissions}
|
44
|
+
end
|
45
|
+
|
46
|
+
Then /^there should be an association add change_log record created$/ do
|
47
|
+
change_log = ChangeLog.where({:item_id => @user.id, :item_type => @user.class.to_s, :attribute_name => @permission.class.to_s}).first
|
48
|
+
change_log.should_not be_blank
|
49
|
+
change_log.old_value.should == ChangeLogger::ActsAsChangeLogger::ACTIONS[:create]
|
50
|
+
change_log.new_value.should == @permission.id.to_s
|
51
|
+
end
|
52
|
+
|
53
|
+
Then /^there should be an association remove change_log record created$/ do
|
54
|
+
change_log = ChangeLog.where({:item_id => @user.id, :item_type => @user.class.to_s, :attribute_name => @permission.class.to_s}).last
|
55
|
+
change_log.should_not be_blank
|
56
|
+
change_log.old_value.should == @permission.id.to_s
|
57
|
+
change_log.new_value.should == ChangeLogger::ActsAsChangeLogger::ACTIONS[:delete]
|
58
|
+
end
|
59
|
+
|
60
|
+
Given /^user does not have the permission "([^"]*)"$/ do |name| #"
|
61
|
+
@permission = Factory.create(:permission)
|
62
|
+
@user.permissions.include?(@permission).should be_false
|
63
|
+
end
|
64
|
+
|
65
|
+
Given /^user has the permission "([^"]*)"$/ do |name| #"
|
66
|
+
@permission = Factory.create(:permission)
|
67
|
+
@user.permissions << @permission
|
68
|
+
@user.permissions.include?(@permission).should be_true
|
69
|
+
end
|
70
|
+
|
71
|
+
When /^I delete the user$/ do
|
72
|
+
@user.destroy
|
73
|
+
end
|
74
|
+
|
75
|
+
When /^I add that permission to user$/ do
|
76
|
+
@user.permissions << @permission
|
77
|
+
@user.permissions.include?(@permission).should be_true
|
78
|
+
end
|
79
|
+
|
80
|
+
When /^I remove that permission from user$/ do
|
81
|
+
@user.permissions.delete(@permission)
|
82
|
+
@user.permissions.include?(@permission).should be_false
|
83
|
+
end
|
84
|
+
|
85
|
+
Then /^there should not be a change_log for any blank attributes$/ do
|
86
|
+
change_logs = ChangeLog.where({:item_id => @user.id, :item_type => @user.class.to_s, :new_value => ChangeLogger::ActsAsChangeLogger::ACTIONS[:delete], :old_value => ''}).first
|
87
|
+
change_logs.should be_blank
|
88
|
+
end
|
89
|
+
|
90
|
+
Then /^there should be change_log records created for all unignored attributes$/ do
|
91
|
+
@user.changes_to_track.each do |name, value|
|
92
|
+
change_log = ChangeLog.where({:item_id => @user.id, :item_type => @user.class.to_s, :attribute_name => name, :new_value => ChangeLogger::ActsAsChangeLogger::ACTIONS[:delete]}).first
|
93
|
+
change_log.should_not be_blank
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
Given /^users name is not "([^"]*)"$/ do |name| #"
|
98
|
+
@user.name.should_not == name
|
99
|
+
end
|
100
|
+
|
101
|
+
When /^I update the name to "([^"]*)"$/ do |name| #"
|
102
|
+
# @user.stub!(:update_attribute).with(name).and_return(true)
|
103
|
+
# @user.update_attribute(:name, name)
|
104
|
+
# @user.name.should == name
|
105
|
+
@user.name.should == @user.name
|
106
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__),"..","..","lib")
|
2
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__),"..","..","spec")
|
3
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__),"..","..","spec","models")
|
4
|
+
require 'active_support'
|
5
|
+
require 'active_support/dependencies'
|
6
|
+
require 'active_record'
|
7
|
+
require 'action_controller'
|
8
|
+
require 'change_logger'
|
9
|
+
|
10
|
+
require 'factory_girl'
|
11
|
+
|
12
|
+
ActiveRecord::Base.establish_connection(
|
13
|
+
:adapter => 'sqlite3',
|
14
|
+
:database => 'test.db',
|
15
|
+
:pool => 5,
|
16
|
+
:timeout => 5000
|
17
|
+
)
|
18
|
+
|
19
|
+
require 'factories'
|
@@ -16,8 +16,9 @@ module ChangeLogger
|
|
16
16
|
self.ignore.push('id', 'created_at', 'updated_at')
|
17
17
|
|
18
18
|
has_many :change_logs, :as => :item, :order => 'change_logs.created_at desc'
|
19
|
-
|
20
|
-
|
19
|
+
after_create :record_object_creation
|
20
|
+
after_update :record_attribute_updates
|
21
|
+
before_destroy :record_object_destruction
|
21
22
|
self.reflect_on_all_associations(:has_and_belongs_to_many).each do |reflection|
|
22
23
|
if reflection.options.keys.include?(:after_add) || reflection.options.keys.include?(:before_add)
|
23
24
|
logger.warn { "WARNING: change_logger adds after_add and after_remove options to has_and_belongs_to_many relationships. You need to combine your current methods with the record_association_* methods in order for change_logger to work correctly." }
|
@@ -31,37 +32,43 @@ module ChangeLogger
|
|
31
32
|
module InstanceMethods
|
32
33
|
|
33
34
|
def record_association_add(object)
|
34
|
-
record_change(object.class.to_s, ACTIONS[:create], object.id)
|
35
|
+
record_change(object.class.to_s, ACTIONS[:create], object.id) if self.persisted?
|
35
36
|
end
|
36
37
|
|
37
38
|
def record_association_remove(object)
|
38
|
-
record_change(object.class.to_s, object.id, ACTIONS[:delete])
|
39
|
+
record_change(object.class.to_s, object.id, ACTIONS[:delete]) if self.persisted?
|
40
|
+
end
|
41
|
+
|
42
|
+
def record_object_creation
|
43
|
+
attributes.delete_if {|k,v| self.class.ignore.include?(k) }.each do |key, value|
|
44
|
+
record_change(key, ACTIONS[:create], value) unless value.blank?
|
45
|
+
end
|
39
46
|
end
|
40
47
|
|
41
48
|
def record_attribute_updates
|
42
|
-
|
49
|
+
changes_to_track.each do |key, value|
|
43
50
|
record_change(key, value[0], value[1])
|
44
|
-
end
|
51
|
+
end
|
45
52
|
end
|
46
53
|
|
47
54
|
def record_object_destruction
|
48
55
|
attributes.each do |key, value|
|
49
|
-
record_change(key,
|
56
|
+
record_change(key, value, ACTIONS[:delete])
|
50
57
|
end
|
51
58
|
end
|
59
|
+
|
60
|
+
def changes_to_track
|
61
|
+
(new_record? ? attributes : changes).delete_if {|k,v| self.class.ignore.include?(k) }
|
62
|
+
end
|
52
63
|
|
53
64
|
private
|
54
|
-
|
55
|
-
def old_value(val)
|
56
|
-
self.new_record? ? ACTIONS[:create] : val
|
57
|
-
end
|
58
65
|
|
59
|
-
def record_change(attribute_name, old_val, new_val)
|
60
|
-
self.change_logs.create
|
66
|
+
def record_change(attribute_name, old_val, new_val)
|
67
|
+
self.change_logs.create(
|
61
68
|
:attribute_name => attribute_name,
|
62
69
|
:old_value => old_val,
|
63
70
|
:new_value => new_val,
|
64
|
-
:
|
71
|
+
:changed_by => whodunnit
|
65
72
|
)
|
66
73
|
end
|
67
74
|
end
|
@@ -4,10 +4,11 @@ class CreateChangeLogs < ActiveRecord::Migration
|
|
4
4
|
t.integer :item_id, :null => false
|
5
5
|
t.string :item_type, :null => false
|
6
6
|
t.string :attribute_name, :old_value, :new_value
|
7
|
-
t.
|
8
|
-
t.
|
7
|
+
t.string :changed_by, :null => false
|
8
|
+
t.datetime :created_at
|
9
9
|
end
|
10
10
|
add_index :change_logs, [:item_type, :item_id]
|
11
|
+
add_index :change_logs, [:changed_by, :created_at]
|
11
12
|
end
|
12
13
|
|
13
14
|
def self.down
|
data/spec/factories.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
class InitTestDb < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :users do |t|
|
4
|
+
t.string :name
|
5
|
+
t.string :persistence_token
|
6
|
+
t.timestamps
|
7
|
+
end
|
8
|
+
create_table :permissions do |t|
|
9
|
+
t.string :name
|
10
|
+
end
|
11
|
+
create_table :permissions_users, :id => false do |t|
|
12
|
+
t.integer :permission_id, :user_id, :null => false
|
13
|
+
end
|
14
|
+
# the create_table below needs to be removed and the one stored in lib/generators/templates/create_change_log should be used
|
15
|
+
create_table :change_logs do |t|
|
16
|
+
t.integer :item_id, :null => false
|
17
|
+
t.string :item_type, :null => false
|
18
|
+
t.string :attribute_name, :old_value, :new_value
|
19
|
+
t.string :changed_by, :null => false
|
20
|
+
t.datetime :created_at
|
21
|
+
end
|
22
|
+
add_index :change_logs, [:item_type, :item_id]
|
23
|
+
add_index :change_logs, [:changed_by, :created_at]
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.down
|
27
|
+
drop_table :users
|
28
|
+
drop_table :permissions
|
29
|
+
drop_table :permissions_users
|
30
|
+
drop_table :change_logs
|
31
|
+
end
|
32
|
+
end
|
data/spec/models/user.rb
ADDED
data.tar.gz.sig
CHANGED
@@ -1,2 +1 @@
|
|
1
|
-
|
2
|
-
�OE����_�Mw}9�����
|
1
|
+
�Ы���{V�?��@��,�õݭ��8���kD[!�����h7cy`�&�;���/E��%�Fc�r9�̕)���p�Ls��P{�H_=���,re�:A����3y|�I��z�)|@��c&�?0����%$B���Do��04�8\D�֪ �k5�ly˄aY1�Hx(.[y\�#ɔ�j�jT^cp-�TF��\R�W��:��Ys#�r��y�����=yG�ѵb|xt+).T��E@.��my��uR
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 3
|
9
|
+
version: 0.0.3
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Dan Engle
|
@@ -35,7 +35,7 @@ cert_chain:
|
|
35
35
|
2MS0NMYj
|
36
36
|
-----END CERTIFICATE-----
|
37
37
|
|
38
|
-
date: 2010-12-
|
38
|
+
date: 2010-12-05 00:00:00 -06:00
|
39
39
|
default_executable:
|
40
40
|
dependencies: []
|
41
41
|
|
@@ -61,6 +61,11 @@ files:
|
|
61
61
|
- Manifest
|
62
62
|
- README
|
63
63
|
- Rakefile
|
64
|
+
- cucumber.yml.bac
|
65
|
+
- features/log_changes.feature
|
66
|
+
- features/step_definitions/log_changes_steps.rb
|
67
|
+
- features/support/env.rb
|
68
|
+
- features/support/hooks.rb
|
64
69
|
- lib/app/models/change_log.rb
|
65
70
|
- lib/change_logger.rb
|
66
71
|
- lib/change_logger/acts_as_change_logger.rb
|
@@ -68,6 +73,10 @@ files:
|
|
68
73
|
- lib/change_logger/whodunnit.rb
|
69
74
|
- lib/generators/change_logger_generator.rb
|
70
75
|
- lib/generators/templates/create_change_logs.rb
|
76
|
+
- spec/factories.rb
|
77
|
+
- spec/migrate/20101201_init_test_db.rb
|
78
|
+
- spec/models/permission.rb
|
79
|
+
- spec/models/user.rb
|
71
80
|
- change_logger.gemspec
|
72
81
|
has_rdoc: true
|
73
82
|
homepage: http://github.com/danengle/awesome_tables
|
metadata.gz.sig
CHANGED
Binary file
|