auditrail 0.0.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.
@@ -0,0 +1,2 @@
1
+ ---
2
+ BUNDLE_DISABLE_SHARED_GEMS: "1"
@@ -0,0 +1,3 @@
1
+ **/*.swp
2
+ **/*.DS_Store
3
+ spec/tmp
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm 1.9.2@auditrail --create
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in auditrail.gemspec
4
+ gemspec
@@ -0,0 +1,73 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ auditrail (0.0.1)
5
+ activerecord (~> 3.0.1)
6
+ railties (~> 3.0.1)
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ abstract (1.0.0)
12
+ actionpack (3.0.3)
13
+ activemodel (= 3.0.3)
14
+ activesupport (= 3.0.3)
15
+ builder (~> 2.1.2)
16
+ erubis (~> 2.6.6)
17
+ i18n (~> 0.4)
18
+ rack (~> 1.2.1)
19
+ rack-mount (~> 0.6.13)
20
+ rack-test (~> 0.5.6)
21
+ tzinfo (~> 0.3.23)
22
+ activemodel (3.0.3)
23
+ activesupport (= 3.0.3)
24
+ builder (~> 2.1.2)
25
+ i18n (~> 0.4)
26
+ activerecord (3.0.3)
27
+ activemodel (= 3.0.3)
28
+ activesupport (= 3.0.3)
29
+ arel (~> 2.0.2)
30
+ tzinfo (~> 0.3.23)
31
+ activesupport (3.0.3)
32
+ arel (2.0.6)
33
+ builder (2.1.2)
34
+ diff-lcs (1.1.2)
35
+ erubis (2.6.6)
36
+ abstract (>= 1.0.0)
37
+ i18n (0.5.0)
38
+ rack (1.2.1)
39
+ rack-mount (0.6.13)
40
+ rack (>= 1.0.0)
41
+ rack-test (0.5.6)
42
+ rack (>= 1.0)
43
+ railties (3.0.3)
44
+ actionpack (= 3.0.3)
45
+ activesupport (= 3.0.3)
46
+ rake (>= 0.8.7)
47
+ thor (~> 0.14.4)
48
+ rake (0.8.7)
49
+ rspec (2.0.1)
50
+ rspec-core (~> 2.0.1)
51
+ rspec-expectations (~> 2.0.1)
52
+ rspec-mocks (~> 2.0.1)
53
+ rspec-core (2.0.1)
54
+ rspec-expectations (2.0.1)
55
+ diff-lcs (>= 1.1.2)
56
+ rspec-mocks (2.0.1)
57
+ rspec-core (~> 2.0.1)
58
+ rspec-expectations (~> 2.0.1)
59
+ rspec-rails (2.0.1)
60
+ rspec (~> 2.0.0)
61
+ sqlite3-ruby (1.3.2)
62
+ thor (0.14.6)
63
+ tzinfo (0.3.23)
64
+
65
+ PLATFORMS
66
+ ruby
67
+
68
+ DEPENDENCIES
69
+ activerecord (~> 3.0.1)
70
+ auditrail!
71
+ railties (~> 3.0.1)
72
+ rspec-rails (~> 2.0.1)
73
+ sqlite3-ruby
@@ -0,0 +1,93 @@
1
+ # auditrail
2
+ An easy and unobtrusive way to track changes on Active Record models.
3
+
4
+
5
+ ## How it works
6
+ This will generate a table named **audits**. **auditrail** will save an *audit entry* each time
7
+ an *audited model* changes.
8
+
9
+ You can find an example application that shows how to use **auditrail**
10
+ [here](https://github.com/MGalv/auditrails_test_app).
11
+
12
+
13
+ ## Installing
14
+ It has only been tested on rails3, in order to install it do:
15
+
16
+ gem install auditrail
17
+
18
+
19
+ ## Usage
20
+ First run the generator to create the *audits* table:
21
+
22
+ rails g auditrail:create
23
+
24
+ That will create a migration. Now Simply add *auditable* to your models like this:
25
+
26
+ class User < ActiveRecord::Base
27
+ auditable
28
+ end
29
+
30
+
31
+ ### Options
32
+ You can define parameter options with a block.
33
+
34
+ #### for_attributes
35
+ Using *for_attributes* you select the fields that you want to be audited. For example:
36
+
37
+ auditable do
38
+ for_attributes "name", "email"
39
+ end
40
+
41
+ This will create an *audit entry* by each time that the fields *name* or *email* change.
42
+
43
+ #### by_user
44
+ Using *by_user* you control who was the *action invoker* or *fields modifier*:
45
+
46
+ auditable do
47
+ by_user "user"
48
+ end
49
+
50
+ Also, you can call the method *by_user* with a block as parameter. For example:
51
+
52
+ auditable do
53
+ by_user do
54
+ "user"
55
+ end
56
+ end
57
+
58
+ This way you may dynamically control what will be saved as the *action invoker* or
59
+ *fields modifier*.
60
+
61
+
62
+ # Development
63
+ If you want to make changes to the gem, then fork it, and first install bundler:
64
+
65
+ gem install bundler
66
+
67
+ Afterwards, install the bundle:
68
+
69
+ bundle install
70
+
71
+
72
+ ## Running the test suite
73
+ Simply run:
74
+
75
+ rake
76
+
77
+
78
+ # Changelog
79
+ Nothing yet.
80
+
81
+
82
+ # To Do
83
+ * Refactor auditrail.rb and its tests.
84
+ * Let the implementor configure where to store the audits.
85
+ * What the audit table name will be.
86
+
87
+ # About the Author
88
+ [Crowd Interactive](http://www.crowdint.com) is an American web design and development
89
+ company that happens to work in Colima, Mexico. We specialize in building and growing
90
+ online retail stores. We don’t work with everyone – just companies we believe in. Call
91
+ us today to see if there’s a fit.
92
+
93
+ Find more info [here](http://www.crowdint.com)!
@@ -0,0 +1,12 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+
6
+ desc "Run all examples"
7
+ RSpec::Core::RakeTask.new(:spec) do |t|
8
+ t.rspec_path = 'rspec'
9
+ t.rspec_opts = %w[--color]
10
+ end
11
+
12
+ task :default => :spec
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "auditrail/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "auditrail"
7
+ s.version = Auditrail::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Luis Galaviz", "Emmanuel Delgado"]
10
+ s.email = ["emmanuel@crowdint.com", "luis.galaviz@crowdint.com"]
11
+ s.homepage = ""
12
+ s.summary = %q{Audits models using serialization}
13
+ s.description = %q{Audits models using serialization}
14
+
15
+ s.rubyforge_project = "auditrail"
16
+ s.add_dependency("activerecord", "~> 3.0.1")
17
+ s.add_dependency("railties", "~> 3.0.1")
18
+ s.add_development_dependency("rspec-rails", "~> 2.0.1")
19
+ s.add_development_dependency("sqlite3-ruby")
20
+
21
+ s.files = `git ls-files`.split("\n")
22
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
23
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
24
+ s.require_paths = ["lib"]
25
+ end
@@ -0,0 +1,85 @@
1
+ require 'active_record'
2
+ require 'active_support/concern'
3
+ require 'yaml'
4
+ require 'generators/migrations'
5
+ require 'generators/model'
6
+
7
+ module Auditrail
8
+
9
+ extend ActiveSupport::Concern
10
+
11
+ module ClassMethods
12
+
13
+ class AuditOptions
14
+
15
+ def initialize(&block)
16
+ instance_eval &block if block
17
+ end
18
+
19
+ def user
20
+ @user
21
+ end
22
+
23
+ def attributes
24
+ @attributes
25
+ end
26
+
27
+ private
28
+ def by_user(user = nil, &block)
29
+ @user = block ? block.call : user
30
+ end
31
+
32
+ def for_attributes(*attributes)
33
+ @attributes = attributes
34
+ end
35
+
36
+ end
37
+
38
+ def auditable(&block)
39
+ audit_options = block ? AuditOptions.new(&block) : AuditOptions.new
40
+
41
+ class_eval do
42
+ before_create do
43
+ track_changes(:creating, audit_options.user) if attributes_changed?(*audit_options.attributes)
44
+ end
45
+
46
+ before_update do
47
+ track_changes(:updating, audit_options.user) if attributes_changed?(*audit_options.attributes)
48
+ end
49
+
50
+ after_save do
51
+ save_tracked_changes if attributes_changed?(*audit_options.attributes)
52
+ end
53
+ end
54
+
55
+ end
56
+
57
+ end
58
+
59
+ module InstanceMethods
60
+
61
+ private
62
+ def attributes_changed?(*options)
63
+ (options - changes.keys) != options || options.empty?
64
+ end
65
+
66
+
67
+ def track_changes(*options)
68
+ action = options[0]
69
+ @audit = Audit.new
70
+ @audit.dumped_changes = YAML.dump(changes)
71
+ @audit.model_changed = self.class
72
+ @audit.action = action
73
+ @audit.invoker = YAML.dump(options[1])
74
+ end
75
+
76
+ def save_tracked_changes
77
+ @audit.element_id = id
78
+ @audit.save
79
+ end
80
+
81
+ end
82
+
83
+ end
84
+
85
+ ActiveRecord::Base.send(:include, Auditrail)
@@ -0,0 +1,3 @@
1
+ module Auditrail
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,16 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/active_record'
3
+
4
+ module Auditrail
5
+ module Generators
6
+ class MigrationsGenerator < Rails::Generators::Base
7
+ source_root File.expand_path("templates", File.dirname(__FILE__))
8
+
9
+ def prepare
10
+ migrations_dir = File.join("db", "migrate")
11
+ file_name = ::ActiveRecord::Generators::Base.next_migration_number(migrations_dir)
12
+ copy_file("audits_table.rb", File.join(migrations_dir, "#{file_name.to_s}_create_audits.rb"))
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,14 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/active_record'
3
+
4
+ module Auditrail
5
+ module Generators
6
+ class ModelGenerator < Rails::Generators::Base
7
+ source_root File.expand_path("templates", File.dirname(__FILE__))
8
+
9
+ def prepare
10
+ copy_file("audit_model.rb", File.join("app", "models", "audit.rb"))
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,15 @@
1
+ require 'yaml'
2
+
3
+ class Audit < ActiveRecord::Base
4
+ def action_invoker
5
+ YAML.load(invoker)
6
+ end
7
+
8
+ def self.model_filter(model_changed)
9
+ where("model_changed = ?", model_changed.to_s.camelize)
10
+ end
11
+
12
+ def self.action_filter(action)
13
+ where("action = ?", action.to_s)
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ class CreateAudits < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :audits do |t|
4
+ t.string :dumped_changes
5
+ t.string :action
6
+ t.string :model_changed
7
+ t.integer :element_id
8
+ t.string :invoker
9
+
10
+ t.timestamps
11
+ end
12
+ end
13
+
14
+ def self.down
15
+ drop_table :audits
16
+ end
17
+ end
@@ -0,0 +1,155 @@
1
+ require 'spec_helper'
2
+ require 'yaml'
3
+ require 'support/active_record'
4
+
5
+ describe 'A test class' do
6
+ include Auditrail::Test::ActiveRecord
7
+
8
+ before do
9
+ connection_open
10
+ generate_migration
11
+ migrate
12
+
13
+ # the blocked passed to auditable will determine the action invoker
14
+ # that will be serialized
15
+ @test_class.class_eval do
16
+ auditable do
17
+ # When using the options by_user you can also pass the parameters as a block.
18
+ # by_user 465
19
+ # or
20
+ # by_user do
21
+ # 465
22
+ # end
23
+
24
+ by_user 465
25
+ end
26
+ end
27
+ end
28
+
29
+ after do
30
+ clean_tmp_path
31
+ connection_close
32
+ end
33
+
34
+ context 'its class should be auditable' do
35
+ it 'contains an auditable method' do
36
+ @test_class.should respond_to(:auditable)
37
+ end
38
+ end
39
+
40
+ context 'basic Audit behavior' do
41
+
42
+ before do
43
+ @test_class.create(:name => "Text")
44
+ end
45
+
46
+ context 'creates a new object' do
47
+
48
+ it "should track the changes in the Test object" do
49
+ audit_changes = @audit_class.first.dumped_changes
50
+ changes_hash = YAML.load(audit_changes)
51
+ changes_hash["name"][0].should eq(nil)
52
+ changes_hash["name"][1].should eq("Text")
53
+ end
54
+
55
+ it "should receive a creating status" do
56
+ @audit_class.first.action.should eq("creating")
57
+ end
58
+
59
+ it "should save the model name of the audited object" do
60
+ @audit_class.first.model_changed.should eq("Test")
61
+ end
62
+
63
+ it 'should save the id of the original affected object' do
64
+ instance = @test_class.first
65
+ @audit_class.first.element_id.should eq(instance.id)
66
+ end
67
+
68
+ it 'should return the action invoker' do
69
+ @audit_class.first.action_invoker.should eq(465)
70
+ end
71
+
72
+ end
73
+
74
+ context 'updates an existing object' do
75
+ it "should receive a creating status" do
76
+ instance = @test_class.first
77
+ instance.name = "Text change"
78
+ instance.save
79
+ @audit_class.last.action.should eq("updating")
80
+ end
81
+ end
82
+
83
+ end
84
+
85
+ context "basic query content behavior" do
86
+
87
+ before do
88
+ @user_class.class_eval do
89
+ auditable
90
+ end
91
+ 10.times do
92
+ @test_class.create(:name => "Text")
93
+ end
94
+
95
+ 5.times do |item_number|
96
+ @user_class.create(:name => "User #{item_number}", :age => 15 + item_number, :email => "abc#{item_number}@abc.com")
97
+ end
98
+ end
99
+
100
+ it "should find the audits by model" do
101
+ @audit_class.model_filter(:user).should have_exactly(5).items
102
+ @audit_class.model_filter(:test).should have_exactly(10).items
103
+ @audit_class.model_filter(:admin).should have_exactly(0).items
104
+ end
105
+
106
+ it "should find the audits by action" do
107
+ 5.times do |item_number|
108
+ test = @test_class.first
109
+ test.name = "Text changed #{item_number}"
110
+ test.save
111
+ end
112
+
113
+ 3.times do |item_number|
114
+ user = @user_class.first
115
+ user.name = "User 1 name changed #{item_number}"
116
+ user.save
117
+ end
118
+
119
+ @audit_class.action_filter(:creating).should have_exactly(15).items
120
+ @audit_class.action_filter(:updating).should have_exactly(8).items
121
+ @audit_class.action_filter(:other).should have_exactly(0).items
122
+ end
123
+ end
124
+
125
+ context "track changes only for selected attributes" do
126
+ before do
127
+ @user_class.class_eval do
128
+ auditable do
129
+ for_attributes "name", "email"
130
+ end
131
+ end
132
+ @user_class.create(:name => "Marco", :age => 15, :email => "marco@abc.com")
133
+ end
134
+
135
+ it "should track only for name and email" do
136
+ user = @user_class.first
137
+ user.name = "Polo"
138
+ user.save
139
+
140
+ user = @user_class.first
141
+ user.email = "polo@abc.com"
142
+ user.save
143
+
144
+ @audit_class.all.should have_exactly(3).items
145
+ end
146
+
147
+ it "should not track changes for age" do
148
+ user = @user_class.first
149
+ user.age = 16
150
+ user.save
151
+
152
+ @audit_class.all.should have_exactly(1).items
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+ require 'support/active_record'
3
+
4
+ describe Auditrail::Generators::MigrationsGenerator do
5
+ include Auditrail::Test::ActiveRecord
6
+
7
+ before {generate_migration}
8
+
9
+ after {clean_tmp_path}
10
+
11
+ it "should generate the migration for the audits tabble into the db/migrate folder" do
12
+ Dir.glob(File.join(File.expand_path(File.join(DESTINATION, "db", "migrate")), "*_create_audits.rb")).should have_exactly(1).items
13
+ end
14
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+ require 'support/active_record'
3
+
4
+ describe Auditrail::Generators::ModelGenerator do
5
+ include Auditrail::Test::ActiveRecord
6
+
7
+ before { generate_model }
8
+
9
+ after {clean_tmp_path}
10
+
11
+ it "should generate the Audit model" do
12
+ file = File.expand_path(File.join(DESTINATION, "app", "models", "audit.rb"))
13
+ File.exist?(file).should be(true)
14
+ end
15
+ end
@@ -0,0 +1,18 @@
1
+ $:.unshift File.join(File.dirname(__FILE__))
2
+ $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
3
+
4
+ require 'auditrail'
5
+ require 'generators/migrations'
6
+ require 'generators/model'
7
+ require 'rails'
8
+ require 'fileutils'
9
+ require 'rake'
10
+
11
+ ENV["RAILS_ENV"] = "test"
12
+ ENV["RAILS_ROOT"] = "tmp"
13
+ DESTINATION = File.expand_path(File.join("spec","tmp"))
14
+ ENV['SCHEMA'] = File.join(DESTINATION, "db", "schema.rb")
15
+
16
+ module Auditrail
17
+ class Application < Rails::Application; end
18
+ end
@@ -0,0 +1,62 @@
1
+ require 'active_record'
2
+
3
+ module Auditrail
4
+ module Test
5
+ module ActiveRecord
6
+
7
+ def migrate
8
+ rake_app = Rake::Application.new
9
+ Rake.application = rake_app
10
+ Rake.application.rake_require File.join("active_record", "railties", "databases")
11
+ Rake::Task.define_task(:environment)
12
+
13
+ ::ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
14
+ ::ActiveRecord::Migrator.migrate(File.join(DESTINATION, "db", "migrate"), ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
15
+ rake_app["db:migrate"].invoke if ::ActiveRecord::Base.schema_format == :ruby
16
+ generate_model
17
+ load File.join(DESTINATION, 'app', 'models', 'audit.rb')
18
+ @audit_class = ::Audit
19
+ end
20
+
21
+ def connection_open
22
+ #::ActiveRecord::Base.logger = Logger.new(STDOUT)
23
+ ::ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
24
+ ::ActiveRecord::Schema.define(:version => 1) do
25
+ create_table :tests do |t|
26
+ t.string :name
27
+ end
28
+
29
+ create_table :users do |t|
30
+ t.string :name
31
+ t.string :email
32
+ t.integer :age
33
+ end
34
+ end
35
+
36
+ @test_class = Object.const_set(:Test, Class.new(::ActiveRecord::Base))
37
+ @user_class = Object.const_set(:User, Class.new(::ActiveRecord::Base))
38
+ end
39
+
40
+ def connection_close
41
+ Object.send(:remove_const, :Test)
42
+ Object.send(:remove_const, :User)
43
+ ::ActiveRecord::Base.connection.tables.each do |table|
44
+ ::ActiveRecord::Base.connection.drop_table(table)
45
+ end
46
+ end
47
+
48
+ def clean_tmp_path
49
+ FileUtils.rm_rf(DESTINATION)
50
+ end
51
+
52
+ def generate_migration
53
+ Auditrail::Generators::MigrationsGenerator.start([] , :destination_root => DESTINATION)
54
+ end
55
+
56
+ def generate_model
57
+ Auditrail::Generators::ModelGenerator.start([] , :destination_root => DESTINATION)
58
+ end
59
+
60
+ end
61
+ end
62
+ end
metadata ADDED
@@ -0,0 +1,142 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: auditrail
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Luis Galaviz
13
+ - Emmanuel Delgado
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-12-22 00:00:00 -06:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: activerecord
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ segments:
30
+ - 3
31
+ - 0
32
+ - 1
33
+ version: 3.0.1
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: railties
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ segments:
45
+ - 3
46
+ - 0
47
+ - 1
48
+ version: 3.0.1
49
+ type: :runtime
50
+ version_requirements: *id002
51
+ - !ruby/object:Gem::Dependency
52
+ name: rspec-rails
53
+ prerelease: false
54
+ requirement: &id003 !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ~>
58
+ - !ruby/object:Gem::Version
59
+ segments:
60
+ - 2
61
+ - 0
62
+ - 1
63
+ version: 2.0.1
64
+ type: :development
65
+ version_requirements: *id003
66
+ - !ruby/object:Gem::Dependency
67
+ name: sqlite3-ruby
68
+ prerelease: false
69
+ requirement: &id004 !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ segments:
75
+ - 0
76
+ version: "0"
77
+ type: :development
78
+ version_requirements: *id004
79
+ description: Audits models using serialization
80
+ email:
81
+ - emmanuel@crowdint.com
82
+ - luis.galaviz@crowdint.com
83
+ executables: []
84
+
85
+ extensions: []
86
+
87
+ extra_rdoc_files: []
88
+
89
+ files:
90
+ - .bundle/config
91
+ - .gitignore
92
+ - .rvmrc
93
+ - Gemfile
94
+ - Gemfile.lock
95
+ - README.md
96
+ - Rakefile
97
+ - auditrail.gemspec
98
+ - lib/auditrail.rb
99
+ - lib/auditrail/version.rb
100
+ - lib/generators/migrations.rb
101
+ - lib/generators/model.rb
102
+ - lib/generators/templates/audit_model.rb
103
+ - lib/generators/templates/audits_table.rb
104
+ - spec/auditrail_spec.rb
105
+ - spec/migrations_spec.rb
106
+ - spec/model_generator_spec.rb
107
+ - spec/spec_helper.rb
108
+ - spec/support/active_record.rb
109
+ has_rdoc: true
110
+ homepage: ""
111
+ licenses: []
112
+
113
+ post_install_message:
114
+ rdoc_options: []
115
+
116
+ require_paths:
117
+ - lib
118
+ required_ruby_version: !ruby/object:Gem::Requirement
119
+ none: false
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ segments:
124
+ - 0
125
+ version: "0"
126
+ required_rubygems_version: !ruby/object:Gem::Requirement
127
+ none: false
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ segments:
132
+ - 0
133
+ version: "0"
134
+ requirements: []
135
+
136
+ rubyforge_project: auditrail
137
+ rubygems_version: 1.3.7
138
+ signing_key:
139
+ specification_version: 3
140
+ summary: Audits models using serialization
141
+ test_files: []
142
+