change_logger 0.0.2 → 0.0.3
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/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
|