acts_as_audited 1.1.1 → 2.0.0

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.
Files changed (59) hide show
  1. data/.gitignore +8 -2
  2. data/.yardopts +3 -0
  3. data/CHANGELOG +10 -2
  4. data/Gemfile +7 -0
  5. data/Gemfile.lock +108 -0
  6. data/LICENSE +2 -2
  7. data/README.textile +143 -0
  8. data/Rakefile +23 -42
  9. data/acts_as_audited.gemspec +13 -68
  10. data/autotest/discover.rb +1 -0
  11. data/lib/acts_as_audited/audit.rb +61 -40
  12. data/lib/acts_as_audited/audit_sweeper.rb +5 -27
  13. data/lib/acts_as_audited/auditor.rb +275 -0
  14. data/lib/acts_as_audited.rb +18 -212
  15. data/lib/generators/acts_as_audited/install_generator.rb +28 -0
  16. data/lib/generators/acts_as_audited/templates/add_association_to_audits.rb +11 -0
  17. data/lib/generators/acts_as_audited/templates/add_comment_to_audits.rb +9 -0
  18. data/lib/generators/acts_as_audited/templates/add_remote_address_to_audits.rb +10 -0
  19. data/{generators/audited_migration/templates/migration.rb → lib/generators/acts_as_audited/templates/install.rb} +9 -4
  20. data/lib/generators/acts_as_audited/templates/rename_association_to_associated.rb +23 -0
  21. data/lib/generators/acts_as_audited/templates/rename_changes_to_audited_changes.rb +9 -0
  22. data/lib/generators/acts_as_audited/templates/rename_parent_to_association.rb +11 -0
  23. data/lib/generators/acts_as_audited/upgrade_generator.rb +63 -0
  24. data/spec/acts_as_audited_spec.rb +473 -0
  25. data/spec/audit_spec.rb +190 -0
  26. data/spec/audit_sweeper_spec.rb +74 -0
  27. data/spec/audited_spec_helpers.rb +16 -0
  28. data/{test → spec}/db/schema.rb +21 -5
  29. data/spec/rails_app/config/application.rb +23 -0
  30. data/spec/rails_app/config/boot.rb +13 -0
  31. data/{test/db → spec/rails_app/config}/database.yml +10 -7
  32. data/spec/rails_app/config/environment.rb +5 -0
  33. data/spec/rails_app/config/environments/development.rb +19 -0
  34. data/spec/rails_app/config/environments/production.rb +33 -0
  35. data/spec/rails_app/config/environments/test.rb +33 -0
  36. data/spec/rails_app/config/initializers/backtrace_silencers.rb +7 -0
  37. data/spec/rails_app/config/initializers/inflections.rb +2 -0
  38. data/spec/rails_app/config/initializers/secret_token.rb +2 -0
  39. data/spec/rails_app/config/routes.rb +6 -0
  40. data/spec/spec_helper.rb +21 -0
  41. data/spec/spec_models.rb +88 -0
  42. data/test/db/version_1.rb +17 -0
  43. data/test/db/version_2.rb +18 -0
  44. data/test/db/version_3.rb +19 -0
  45. data/test/db/version_4.rb +20 -0
  46. data/test/db/version_5.rb +18 -0
  47. data/test/install_generator_test.rb +17 -0
  48. data/test/test_helper.rb +11 -67
  49. data/test/upgrade_generator_test.rb +65 -0
  50. metadata +106 -93
  51. data/README +0 -70
  52. data/VERSION +0 -1
  53. data/generators/audited_migration/USAGE +0 -7
  54. data/generators/audited_migration/audited_migration_generator.rb +0 -7
  55. data/init.rb +0 -1
  56. data/rails/init.rb +0 -8
  57. data/test/acts_as_audited_test.rb +0 -374
  58. data/test/audit_sweeper_test.rb +0 -31
  59. data/test/audit_test.rb +0 -179
data/.gitignore CHANGED
@@ -1,4 +1,10 @@
1
1
  acts_as_audited_plugin.sqlite3.db
2
- test/debug.log
2
+ *.log
3
+ doc/
3
4
  coverage/
4
- pkg
5
+ pkg
6
+ *.swp
7
+ .bundle
8
+ tmp/*
9
+ .yardoc
10
+ .rvmrc
data/.yardopts ADDED
@@ -0,0 +1,3 @@
1
+ --no-private
2
+ --title acts_as_audited
3
+ --exclude lib/generators
data/CHANGELOG CHANGED
@@ -1,8 +1,16 @@
1
- acts_as_audited ChangeLog
1
+ acts_as_audited ChangeLog
2
2
  -------------------------------------------------------------------------------
3
+
4
+ * 2011-09-09 - Rails 3.x support
5
+ Support for associated audits
6
+ Support for remote IP address storage
7
+ Plenty of bug fixes and refactoring
8
+ [kennethkalmer, ineu, PatrickMa, jrozner, dwarburton, bsiggelkow, dgm]
3
9
  * 2009-01-27 - Store old and new values for updates, and store all attributes on destroy.
4
10
  Refactored revisioning methods to work as expected
5
11
  * 2008-10-10 - changed to make it work in development mode
12
+ * 2008-09-24 - Add ability to record parent record of the record being audited
13
+ [Kenneth Kalmer]
6
14
  * 2008-04-19 - refactored to make compatible with dirty tracking in edge rails
7
15
  and to stop storing both old and new values in a single audit
8
16
  * 2008-04-18 - Fix NoMethodError when trying to access the :previous revision
@@ -22,4 +30,4 @@
22
30
  that saves the new value after every change and not just the
23
31
  first, and performs proper type-casting before doing comparisons
24
32
  * 2006-08-14 - The "changes" are now saved as a serialized hash
25
- * 2006-07-21 - initial version
33
+ * 2006-07-21 - initial version
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem "rails", ">= 3.0.3"
4
+ gem "sqlite3"
5
+ gem "rspec-rails", "~> 2.4.0"
6
+ gem "rcov"
7
+ gem "yard"
data/Gemfile.lock ADDED
@@ -0,0 +1,108 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ actionmailer (3.1.0)
5
+ actionpack (= 3.1.0)
6
+ mail (~> 2.3.0)
7
+ actionpack (3.1.0)
8
+ activemodel (= 3.1.0)
9
+ activesupport (= 3.1.0)
10
+ builder (~> 3.0.0)
11
+ erubis (~> 2.7.0)
12
+ i18n (~> 0.6)
13
+ rack (~> 1.3.2)
14
+ rack-cache (~> 1.0.3)
15
+ rack-mount (~> 0.8.2)
16
+ rack-test (~> 0.6.1)
17
+ sprockets (~> 2.0.0)
18
+ activemodel (3.1.0)
19
+ activesupport (= 3.1.0)
20
+ bcrypt-ruby (~> 3.0.0)
21
+ builder (~> 3.0.0)
22
+ i18n (~> 0.6)
23
+ activerecord (3.1.0)
24
+ activemodel (= 3.1.0)
25
+ activesupport (= 3.1.0)
26
+ arel (~> 2.2.1)
27
+ tzinfo (~> 0.3.29)
28
+ activeresource (3.1.0)
29
+ activemodel (= 3.1.0)
30
+ activesupport (= 3.1.0)
31
+ activesupport (3.1.0)
32
+ multi_json (~> 1.0)
33
+ arel (2.2.1)
34
+ bcrypt-ruby (3.0.0)
35
+ builder (3.0.0)
36
+ diff-lcs (1.1.3)
37
+ erubis (2.7.0)
38
+ hike (1.2.1)
39
+ i18n (0.6.0)
40
+ mail (2.3.0)
41
+ i18n (>= 0.4.0)
42
+ mime-types (~> 1.16)
43
+ treetop (~> 1.4.8)
44
+ mime-types (1.16)
45
+ multi_json (1.0.3)
46
+ polyglot (0.3.2)
47
+ rack (1.3.2)
48
+ rack-cache (1.0.3)
49
+ rack (>= 0.4)
50
+ rack-mount (0.8.3)
51
+ rack (>= 1.0.0)
52
+ rack-ssl (1.3.2)
53
+ rack
54
+ rack-test (0.6.1)
55
+ rack (>= 1.0)
56
+ rails (3.1.0)
57
+ actionmailer (= 3.1.0)
58
+ actionpack (= 3.1.0)
59
+ activerecord (= 3.1.0)
60
+ activeresource (= 3.1.0)
61
+ activesupport (= 3.1.0)
62
+ bundler (~> 1.0)
63
+ railties (= 3.1.0)
64
+ railties (3.1.0)
65
+ actionpack (= 3.1.0)
66
+ activesupport (= 3.1.0)
67
+ rack-ssl (~> 1.3.2)
68
+ rake (>= 0.8.7)
69
+ rdoc (~> 3.4)
70
+ thor (~> 0.14.6)
71
+ rake (0.9.2)
72
+ rcov (0.9.10)
73
+ rdoc (3.9.4)
74
+ rspec (2.4.0)
75
+ rspec-core (~> 2.4.0)
76
+ rspec-expectations (~> 2.4.0)
77
+ rspec-mocks (~> 2.4.0)
78
+ rspec-core (2.4.0)
79
+ rspec-expectations (2.4.0)
80
+ diff-lcs (~> 1.1.2)
81
+ rspec-mocks (2.4.0)
82
+ rspec-rails (2.4.1)
83
+ actionpack (~> 3.0)
84
+ activesupport (~> 3.0)
85
+ railties (~> 3.0)
86
+ rspec (~> 2.4.0)
87
+ sprockets (2.0.0)
88
+ hike (~> 1.2)
89
+ rack (~> 1.0)
90
+ tilt (!= 1.3.0, ~> 1.1)
91
+ sqlite3 (1.3.4)
92
+ thor (0.14.6)
93
+ tilt (1.3.3)
94
+ treetop (1.4.10)
95
+ polyglot
96
+ polyglot (>= 0.3.1)
97
+ tzinfo (0.3.29)
98
+ yard (0.7.2)
99
+
100
+ PLATFORMS
101
+ ruby
102
+
103
+ DEPENDENCIES
104
+ rails (>= 3.0.3)
105
+ rcov
106
+ rspec-rails (~> 2.4.0)
107
+ sqlite3
108
+ yard
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright © 2008 Brandon Keepers - Collective Idea
1
+ Copyright © 2010 Brandon Keepers - Collective Idea
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to deal
@@ -16,4 +16,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
16
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
17
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
18
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
- THE SOFTWARE.
19
+ THE SOFTWARE.
data/README.textile ADDED
@@ -0,0 +1,143 @@
1
+ h1. acts_as_audited
2
+
3
+ +acts_as_audited+ is an ActiveRecord extension that logs all changes to your
4
+ models in an audits table, with optional revision comments. +acts_as_audited+
5
+ has been updated to work with Rails 3, to use it with older version of Rails,
6
+ please see the <tt>1.1-stable</tt> branch.
7
+
8
+ h2. Installation
9
+
10
+ In <tt>Gemfile</tt>:
11
+
12
+ @gem "acts_as_audited", "2.0.0"@
13
+
14
+ In your application root, run:
15
+
16
+ @$ bundle install@
17
+
18
+ Generate the migration:
19
+
20
+ * If installing without a previous version of +acts_as_audited+ or you do not mind overwriting your audits table:
21
+
22
+ @$ rails g acts_as_audited:install@
23
+
24
+ * If upgrading from a previous version of +acts_as_audited+ you might need some alterations to the audits table:
25
+
26
+ @$ rails g acts_as_audited:upgrade@
27
+
28
+ * After running one of the generators:
29
+
30
+ @$ rake db:migrate@
31
+
32
+ h2. Rails deprecation warning
33
+
34
+ Currently the gem causes the following deprecation warning to be emitted:
35
+
36
+ @DEPRECATION WARNING: reorder is deprecated. Please use except(:order).order(...) instead. (called from <class:Audit> at /Users/kenneth/Code/FOSS/acts_as_audited/lib/acts_as_audited/audit.rb:26)@
37
+
38
+ I'm well aware of the fact, and working towards a solution. The issue has also been brought up on the Rails lighthouse as "#6011":https://rails.lighthouseapp.com/projects/8994/tickets/6011-exceptorderorder-is-not-working-in-scopes. I'm keeping an eye on the issue and working towards another possible solution.
39
+
40
+ h2. Upgrading
41
+
42
+ Upgrading to Rails 3, or even between point releases of +acts_as_audited+, might require alterations to the audits table. After every upgrade please run the following generator:
43
+
44
+ @$ rails g acts_as_audited:upgrade@
45
+
46
+ The upgrade generator will only generate migrations that are missing, or no migrations at all if you are up to date.
47
+
48
+ h2. Usage
49
+
50
+ Declare +acts_as_audited+ on your models:
51
+
52
+ <pre><code>class User < ActiveRecord::Base
53
+ acts_as_audited :except => [:password, :mistress]
54
+ end
55
+ </code></pre>
56
+
57
+ Within a web request, will automatically record the user that made the change if your controller has a +current_user+ method. Comments can be added to an audit by setting <tt>model.audit_comments</tt>
58
+ before create/update/destroy. If the <tt>:comment_required</tt> option is given to +acts_as_audited+,
59
+ the save/update/destroy action will fail with add an error on <tt>model.audit_comment</tt> and triggering a
60
+ transaction rollback if <tt>model.audit_comment</tt> is nil.
61
+
62
+ To record an audit for an associated model, use the <tt>:associated_with</tt> option.
63
+
64
+ <pre><code>class User < ActiveRecord::Base
65
+ acts_as_audited :associated_with => :company
66
+ end
67
+ </code></pre>
68
+
69
+ If desired, the associated model can access its audits using <tt>has_associated_audits</tt>.
70
+
71
+ <pre><code>class Company < ActiveRecord::Base
72
+ has_many :users
73
+ has_associated_audits
74
+ end
75
+ </code></pre>
76
+
77
+ To record a user in the audits outside of a web request, you can use +as_user+:
78
+
79
+ <pre><code>Audit.as_user(user) do
80
+ # Perform changes on audited models
81
+ end
82
+ </code></pre>
83
+
84
+ h2. Caveats
85
+
86
+ If your model declares +attr_accessible+ after +acts_as_audited+, you need to set <tt>:protect</tt> to false. acts_as_audited uses +attr_protected+ internally to prevent malicious users from unassociating your audits, and Rails does not allow both +attr_protected+ and +attr_accessible+. It will default to false if +attr_accessible+ is called before +acts_as_audited+, but needs to be explicitly set if it is called after.
87
+
88
+ <pre><code>class User < ActiveRecord::Base
89
+ acts_as_audited :protect => false
90
+ attr_accessible :name
91
+ end
92
+ </code></pre>
93
+
94
+ Another caveat is documented in "issue 26":https://github.com/collectiveidea/acts_as_audited/issues#issue/26, where an audit created on the first request to the server does not have a user. Please review the Github issue for more details on how to fix this. It does not appear to affect Rails 3.
95
+
96
+ h2. Compatability
97
+
98
+ +acts_as_audited+ works with Rails 3.0.3 – 3.1.0. For older versions of Rails, please see the <tt>1.1-stable</tt> branch.
99
+
100
+ h2. Getting Help
101
+
102
+ Review the documentation at "http://rdoc.info/github/collectiveidea/acts_as_audited":http://rdoc.info/github/collectiveidea/acts_as_audited
103
+
104
+ Join "the mailing list":http://groups.google.com/group/acts_as_audited for getting help or offering suggestions.
105
+
106
+ h2. Branches
107
+
108
+ The <tt>master</tt> branch is considered stable, and you should be able to use it at any time.
109
+
110
+ h2. Contributing
111
+
112
+ In the spirit of "free software":http://www.fsf.org/licensing/essays/free-sw.html, **everyone** is encouraged to help improve this project.
113
+
114
+ Here are some ways *you* can contribute:
115
+
116
+ * using alpha, beta, and prerelease versions
117
+ * reporting bugs
118
+ * suggesting new features
119
+ * writing or editing documentation
120
+ * writing specifications
121
+ * writing code (**no patch is too small**: fix typos, add comments, clean up inconsistent whitespace)
122
+ * refactoring code
123
+ * closing "issues":https://github.com/collectiveidea/acts_as_audited/issues
124
+ * reviewing patches
125
+
126
+ h2. Submitting an Issue
127
+
128
+ We use the "GitHub issue tracker":https://github.com/collectiveidea/acts_as_audited/issues to track bugs
129
+ and features. Before submitting a bug report or feature request, check to make sure it hasn't already
130
+ been submitted. You can indicate support for an existing issuse by voting it up. When submitting a
131
+ bug report, please include a "Gist":https://gist.github.com/ that includes a stack trace and any
132
+ details that may be necessary to reproduce the bug, including your gem version, Ruby version, and
133
+ operating system. Ideally, a bug report should include a pull request with failing specs.
134
+
135
+ h2. Submitting a Pull Request
136
+
137
+ 1. Fork the project.
138
+ 2. Create a topic branch.
139
+ 3. Implement your feature or bug fix.
140
+ 4. Add specs for your feature or bug fix.
141
+ 5. Run @bundle exec rake@. If your changes are not 100% covered and passing, go back to step 4.
142
+ 6. Commit and push your changes.
143
+ 7. Submit a pull request. Please do not include changes to the gemspec, version, or history file. (If you want to create your own version for some reason, please do so in a separate commit.)
data/Rakefile CHANGED
@@ -1,57 +1,38 @@
1
1
  require 'rake'
2
- require 'load_multi_rails_rake_tasks'
2
+ require 'rspec/core/rake_task'
3
3
  require 'rake/testtask'
4
- require 'rake/rdoctask'
4
+ require 'bundler'
5
+ Bundler::GemHelper.install_tasks
5
6
 
6
- desc 'Default: run tests.'
7
- task :default => :test
7
+ $:.unshift File.expand_path('../lib', __FILE__)
8
8
 
9
- begin
10
- require 'jeweler'
11
- Jeweler::Tasks.new do |gem|
12
- gem.name = "acts_as_audited"
13
- gem.summary = %Q{ActiveRecord extension that logs all changes to your models in an audits table}
14
- gem.email = "brandon@opensoul.org"
15
- gem.homepage = "http://github.com/collectiveidea/acts_as_audited"
16
- gem.authors = ["Brandon Keepers"]
17
- gem.add_dependency 'activerecord', '>=2.1'
18
- gem.add_development_dependency "thoughtbot-shoulda"
19
- gem.add_development_dependency "jnunemaker-matchy"
20
- # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
21
- end
22
- # Jeweler::GemcutterTasks.new
23
- rescue LoadError
24
- puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
9
+ require 'acts_as_audited'
10
+
11
+ desc 'Default: run specs and tests'
12
+ task :default => [:spec, :test]
13
+
14
+ RSpec::Core::RakeTask.new do |t|
15
+ t.rspec_opts = ["-c", "-f progress", "-r ./spec/spec_helper.rb"]
16
+ t.pattern = 'spec/*_spec.rb'
25
17
  end
26
18
 
27
- desc 'Test the acts_as_audited plugin'
19
+ RSpec::Core::RakeTask.new(:rcov) do |t|
20
+ t.rcov = true
21
+ t.rcov_opts = %q[--exclude "spec"]
22
+ end
23
+
24
+ desc 'Test the acts_as_audited generators'
28
25
  Rake::TestTask.new(:test) do |t|
29
26
  t.libs << 'lib'
30
- t.pattern = 'test/**/*_test.rb'
27
+ t.libs << 'test'
28
+ t.pattern = 'test/*_test.rb'
31
29
  t.verbose = true
32
30
  end
33
31
 
34
- task :test => :check_dependencies
35
-
36
32
  begin
37
- require 'rcov/rcovtask'
38
- Rcov::RcovTask.new do |test|
39
- test.libs << 'test'
40
- test.pattern = 'test/**/*_test.rb'
41
- test.verbose = true
42
- test.rcov_opts = %w(--exclude test,/usr/lib/ruby,/Library/Ruby,$HOME/.gem --sort coverage)
43
- end
33
+ require 'yard'
34
+ YARD::Rake::YardocTask.new
44
35
  rescue LoadError
45
- task :rcov do
46
- abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
47
- end
36
+ puts "YARD (or a dependency) not available. Install it with: bundle install"
48
37
  end
49
38
 
50
- desc 'Generate documentation for the acts_as_audited plugin.'
51
- Rake::RDocTask.new(:rdoc) do |rdoc|
52
- rdoc.rdoc_dir = 'doc'
53
- rdoc.title = 'acts_as_audited'
54
- rdoc.options << '--line-numbers' << '--inline-source'
55
- rdoc.rdoc_files.include('README')
56
- rdoc.rdoc_files.include('lib/**/*.rb')
57
- end
@@ -1,73 +1,18 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
1
  # -*- encoding: utf-8 -*-
5
2
 
6
- Gem::Specification.new do |s|
7
- s.name = %q{acts_as_audited}
8
- s.version = "1.1.1"
3
+ Gem::Specification.new do |gem|
4
+ gem.add_runtime_dependency(%q<rails>, [">= 3.0.3"])
9
5
 
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Brandon Keepers"]
12
- s.date = %q{2010-04-03}
13
- s.email = %q{brandon@opensoul.org}
14
- s.extra_rdoc_files = [
15
- "LICENSE",
16
- "README"
17
- ]
18
- s.files = [
19
- ".gitignore",
20
- "CHANGELOG",
21
- "LICENSE",
22
- "README",
23
- "Rakefile",
24
- "VERSION",
25
- "acts_as_audited.gemspec",
26
- "generators/audited_migration/USAGE",
27
- "generators/audited_migration/audited_migration_generator.rb",
28
- "generators/audited_migration/templates/migration.rb",
29
- "init.rb",
30
- "lib/acts_as_audited.rb",
31
- "lib/acts_as_audited/audit.rb",
32
- "lib/acts_as_audited/audit_sweeper.rb",
33
- "rails/init.rb",
34
- "test/acts_as_audited_test.rb",
35
- "test/audit_sweeper_test.rb",
36
- "test/audit_test.rb",
37
- "test/db/database.yml",
38
- "test/db/schema.rb",
39
- "test/test_helper.rb"
40
- ]
41
- s.homepage = %q{http://github.com/collectiveidea/acts_as_audited}
42
- s.rdoc_options = ["--charset=UTF-8"]
43
- s.require_paths = ["lib"]
44
- s.rubygems_version = %q{1.3.6}
45
- s.summary = %q{ActiveRecord extension that logs all changes to your models in an audits table}
46
- s.test_files = [
47
- "test/acts_as_audited_test.rb",
48
- "test/audit_sweeper_test.rb",
49
- "test/audit_test.rb",
50
- "test/db/schema.rb",
51
- "test/test_helper.rb"
52
- ]
53
-
54
- if s.respond_to? :specification_version then
55
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
56
- s.specification_version = 3
57
-
58
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
59
- s.add_runtime_dependency(%q<activerecord>, [">= 2.1"])
60
- s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
61
- s.add_development_dependency(%q<jnunemaker-matchy>, [">= 0"])
62
- else
63
- s.add_dependency(%q<activerecord>, [">= 2.1"])
64
- s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
65
- s.add_dependency(%q<jnunemaker-matchy>, [">= 0"])
66
- end
67
- else
68
- s.add_dependency(%q<activerecord>, [">= 2.1"])
69
- s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
70
- s.add_dependency(%q<jnunemaker-matchy>, [">= 0"])
71
- end
6
+ gem.authors = ["Brandon Keepers", "Kenneth Kalmer"]
7
+ gem.email = 'brandon@opensoul.org'
8
+ gem.required_rubygems_version = Gem::Requirement.new('>= 1.3.6')
9
+ gem.files = `git ls-files`.split("\n")
10
+ gem.homepage = %q{http://github.com/collectiveidea/acts_as_audited}
11
+ gem.rdoc_options = ["--main", "README.rdoc", "--line-numbers", "--inline-source"]
12
+ gem.require_paths = ["lib"]
13
+ gem.name = 'acts_as_audited'
14
+ gem.summary = %q{ActiveRecord extension that logs all changes to your models in an audits table}
15
+ gem.test_files = `git ls-files -- spec/* test/*`.split("\n")
16
+ gem.version = "2.0.0"
72
17
  end
73
18
 
@@ -0,0 +1 @@
1
+ Autotest.add_discovery { "rspec2" }
@@ -5,37 +5,75 @@ require 'set'
5
5
  # * <tt>auditable</tt>: the ActiveRecord model that was changed
6
6
  # * <tt>user</tt>: the user that performed the change; a string or an ActiveRecord model
7
7
  # * <tt>action</tt>: one of create, update, or delete
8
- # * <tt>changes</tt>: a serialized hash of all the changes
8
+ # * <tt>audited_changes</tt>: a serialized hash of all the changes
9
+ # * <tt>comment</tt>: a comment set with the audit
9
10
  # * <tt>created_at</tt>: Time that the change was performed
10
11
  #
11
12
  class Audit < ActiveRecord::Base
12
13
  belongs_to :auditable, :polymorphic => true
13
14
  belongs_to :user, :polymorphic => true
15
+ belongs_to :associated, :polymorphic => true
14
16
 
15
17
  before_create :set_version_number, :set_audit_user
16
18
 
17
- serialize :changes
19
+ serialize :audited_changes
18
20
 
19
21
  cattr_accessor :audited_class_names
20
22
  self.audited_class_names = Set.new
21
23
 
22
- def self.audited_classes
23
- self.audited_class_names.map(&:constantize)
24
- end
24
+ # Order by ver
25
+ default_scope order(:version)
26
+ scope :descending, reorder("version DESC")
27
+
28
+ class << self
29
+
30
+ # Returns the list of classes that are being audited
31
+ def audited_classes
32
+ audited_class_names.map(&:constantize)
33
+ end
34
+
35
+ # All audits made during the block called will be recorded as made
36
+ # by +user+. This method is hopefully threadsafe, making it ideal
37
+ # for background operations that require audit information.
38
+ def as_user(user, &block)
39
+ Thread.current[:acts_as_audited_user] = user
40
+
41
+ yieldval = yield
42
+
43
+ Thread.current[:acts_as_audited_user] = nil
44
+
45
+ yieldval
46
+ end
47
+
48
+ # @private
49
+ def reconstruct_attributes(audits)
50
+ attributes = {}
51
+ result = audits.collect do |audit|
52
+ attributes.merge!(audit.new_attributes).merge!(:version => audit.version)
53
+ yield attributes if block_given?
54
+ end
55
+ block_given? ? result : attributes
56
+ end
25
57
 
26
- # All audits made during the block called will be recorded as made
27
- # by +user+. This method is hopefully threadsafe, making it ideal
28
- # for background operations that require audit information.
29
- def self.as_user(user, &block)
30
- Thread.current[:acts_as_audited_user] = user
58
+ # @private
59
+ def assign_revision_attributes(record, attributes)
60
+ attributes.each do |attr, val|
61
+ record = record.dup if record.frozen?
31
62
 
32
- yield
63
+ if record.respond_to?("#{attr}=")
64
+ record.attributes.has_key?(attr.to_s) ?
65
+ record[attr] = val :
66
+ record.send("#{attr}=", val)
67
+ end
68
+ end
69
+ record
70
+ end
33
71
 
34
- Thread.current[:acts_as_audited_user] = nil
35
72
  end
36
73
 
37
74
  # Allows user to be set to either a string or an ActiveRecord object
38
- def user_as_string=(user) #:nodoc:
75
+ # @private
76
+ def user_as_string=(user)
39
77
  # reset both either way
40
78
  self.user_as_model = self.username = nil
41
79
  user.is_a?(ActiveRecord::Base) ?
@@ -45,61 +83,44 @@ class Audit < ActiveRecord::Base
45
83
  alias_method :user_as_model=, :user=
46
84
  alias_method :user=, :user_as_string=
47
85
 
48
- def user_as_string #:nodoc:
86
+ # @private
87
+ def user_as_string
49
88
  self.user_as_model || self.username
50
89
  end
51
90
  alias_method :user_as_model, :user
52
91
  alias_method :user, :user_as_string
53
92
 
93
+ # Return an instance of what the object looked like at this revision. If
94
+ # the object has been destroyed, this will be a new record.
54
95
  def revision
55
96
  clazz = auditable_type.constantize
56
- returning clazz.find_by_id(auditable_id) || clazz.new do |m|
97
+ ( clazz.find_by_id(auditable_id) || clazz.new ).tap do |m|
57
98
  Audit.assign_revision_attributes(m, self.class.reconstruct_attributes(ancestors).merge({:version => version}))
58
99
  end
59
100
  end
60
101
 
102
+ # Return all audits older than the current one.
61
103
  def ancestors
62
- self.class.find(:all, :order => 'version',
63
- :conditions => ['auditable_id = ? and auditable_type = ? and version <= ?',
104
+ self.class.where(['auditable_id = ? and auditable_type = ? and version <= ?',
64
105
  auditable_id, auditable_type, version])
65
106
  end
66
107
 
67
108
  # Returns a hash of the changed attributes with the new values
68
109
  def new_attributes
69
- (changes || {}).inject({}.with_indifferent_access) do |attrs,(attr,values)|
70
- attrs[attr] = Array(values).last
110
+ (audited_changes || {}).inject({}.with_indifferent_access) do |attrs,(attr,values)|
111
+ attrs[attr] = values.is_a?(Array) ? values.last : values
71
112
  attrs
72
113
  end
73
114
  end
74
115
 
75
116
  # Returns a hash of the changed attributes with the old values
76
117
  def old_attributes
77
- (changes || {}).inject({}.with_indifferent_access) do |attrs,(attr,values)|
118
+ (audited_changes || {}).inject({}.with_indifferent_access) do |attrs,(attr,values)|
78
119
  attrs[attr] = Array(values).first
79
120
  attrs
80
121
  end
81
122
  end
82
123
 
83
- def self.reconstruct_attributes(audits)
84
- attributes = {}
85
- result = audits.collect do |audit|
86
- attributes.merge!(audit.new_attributes).merge!(:version => audit.version)
87
- yield attributes if block_given?
88
- end
89
- block_given? ? result : attributes
90
- end
91
-
92
- def self.assign_revision_attributes(record, attributes)
93
- attributes.each do |attr, val|
94
- if record.respond_to?("#{attr}=")
95
- record.attributes.has_key?(attr.to_s) ?
96
- record[attr] = val :
97
- record.send("#{attr}=", val)
98
- end
99
- end
100
- record
101
- end
102
-
103
124
  private
104
125
 
105
126
  def set_version_number