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 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.2') do |p|
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
@@ -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.2"
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-02}
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'
@@ -0,0 +1,4 @@
1
+ Before do
2
+ User.delete_all
3
+ Permission.delete_all
4
+ end
@@ -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
- after_save :record_attribute_updates
20
- after_destroy :record_object_destruction
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
- self.changes.delete_if { |k,v| self.class.ignore.include?(k) }.each do |key, value|
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, old_value(value), ACTIONS[:delete])
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
- :changed_by_id => whodunnit.id
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.integer :changed_by_id, :null => false
8
- t.timestamps
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,10 @@
1
+ require 'user'
2
+ require 'permission'
3
+
4
+ Factory.define :user do |f|
5
+ f.name "bob"
6
+ end
7
+
8
+ Factory.define :permission do |f|
9
+ f.name "admin"
10
+ end
@@ -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
@@ -0,0 +1,4 @@
1
+ class Permission < ActiveRecord::Base
2
+ has_and_belongs_to_many :users
3
+ validates_uniqueness_of :name
4
+ end
@@ -0,0 +1,5 @@
1
+ class User < ActiveRecord::Base
2
+ has_and_belongs_to_many :permissions
3
+ acts_as_change_logger :ignore => [:persistence_token]
4
+ validates_uniqueness_of :name
5
+ end
data.tar.gz.sig CHANGED
@@ -1,2 +1 @@
1
- $���S�*y2�����d���5���?PWh�����Gf(�7��.�Ul Rm8{�.��?�ߗG3��q��.騾S�Ȟ��<������4d;�/��!D��^3�$��T��ݷ�k��M��3r��p�
2
- �OE����_�Mw}9�����
1
+ �Ы���{V�?��@��,�õݭ��8���kD[!�����h7cy`�&�;���/E��%�Fcr9�̕)���p Ls��P{�H_=���,re�:A����3y|�I��z�)|@��c&�?0����%$B���Do��048\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
- - 2
9
- version: 0.0.2
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-02 00:00:00 -06:00
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