ar-audit-tracer 0.1.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.
- data/.document +5 -0
- data/.rvmrc +2 -0
- data/LICENSE +20 -0
- data/README.rdoc +34 -0
- data/Rakefile +52 -0
- data/VERSION +1 -0
- data/ar-audit-tracer.gemspec +57 -0
- data/lib/ar-audit-tracer.rb +133 -0
- data/lib/concern/audit/author.rb +15 -0
- data/test/concern/audit/author_test.rb +38 -0
- data/test/helper.rb +34 -0
- data/test/resources/models.rb +9 -0
- data/test/resources/schema.rb +16 -0
- data/test/test_ar-audit-tracer.rb +93 -0
- metadata +82 -0
data/.document
ADDED
data/.rvmrc
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Martin Schweizer
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
= ar-audit-tracer
|
2
|
+
|
3
|
+
|
4
|
+
== Summary
|
5
|
+
|
6
|
+
<i>ar-audit-tracer</i> patches ActiveRecord so modifiers of a record can be traked on saving (insert/update).
|
7
|
+
It works exactly like 'timestamps' (see usage below).
|
8
|
+
|
9
|
+
|
10
|
+
== Usage
|
11
|
+
|
12
|
+
=== Migration
|
13
|
+
|
14
|
+
In a models migration add:
|
15
|
+
t.authors
|
16
|
+
|
17
|
+
This will add columns +created_by+ and +updated_by+ of type +:string+ to your model.
|
18
|
+
|
19
|
+
In case you want to use another type, simply pass the type as argument, e.g.
|
20
|
+
t.authors(:integer)
|
21
|
+
|
22
|
+
=== Usage
|
23
|
+
|
24
|
+
All you need to do is to set the current author such as e.g:
|
25
|
+
Concern::Audit::Author.current="bad_man"
|
26
|
+
|
27
|
+
Each ActiveRecord +save+ or +update+ then will set the respetive attributes +created_by+ and +modified_by+ automatically, whereas the modifier is set to the same value as the creator on model creation.
|
28
|
+
|
29
|
+
In a Rails Application you would set the author as described above in a +before_filter+.
|
30
|
+
+Concern::Audit::Author+ stores the author in a Thread-Local variable.
|
31
|
+
|
32
|
+
== Additional Notes
|
33
|
+
In case you need associations to a respective Author Model you have to set them up yourselfs.
|
34
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "ar-audit-tracer"
|
8
|
+
gem.summary = %Q{Track creator/modifiers of you AR Models similar to timestamps.}
|
9
|
+
gem.description = %Q{Handles ActiveRecord authors in the same way as timstamps.}
|
10
|
+
gem.email = "contact@verticonaut.me"
|
11
|
+
gem.homepage = "http://github.com/verticonaut/ar-audit-tracer"
|
12
|
+
gem.authors = ["Martin Schweizer"]
|
13
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
14
|
+
end
|
15
|
+
Jeweler::GemcutterTasks.new
|
16
|
+
rescue LoadError
|
17
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'rake/testtask'
|
21
|
+
Rake::TestTask.new(:test) do |test|
|
22
|
+
test.libs << 'lib' << 'test'
|
23
|
+
test.pattern = 'test/**/test_*.rb'
|
24
|
+
test.verbose = true
|
25
|
+
end
|
26
|
+
|
27
|
+
begin
|
28
|
+
require 'rcov/rcovtask'
|
29
|
+
Rcov::RcovTask.new do |test|
|
30
|
+
test.libs << 'test'
|
31
|
+
test.pattern = 'test/**/test_*.rb'
|
32
|
+
test.verbose = true
|
33
|
+
end
|
34
|
+
rescue LoadError
|
35
|
+
task :rcov do
|
36
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
task :test => :check_dependencies
|
41
|
+
|
42
|
+
task :default => :test
|
43
|
+
|
44
|
+
require 'rake/rdoctask'
|
45
|
+
Rake::RDocTask.new do |rdoc|
|
46
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
47
|
+
|
48
|
+
rdoc.rdoc_dir = 'rdoc'
|
49
|
+
rdoc.title = "ar-audit-tracer #{version}"
|
50
|
+
rdoc.rdoc_files.include('README*')
|
51
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
52
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{ar-audit-tracer}
|
8
|
+
s.version = "0.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Martin Schweizer"]
|
12
|
+
s.date = %q{2010-11-27}
|
13
|
+
s.description = %q{Handles ActiveRecord authors in the same way as timstamps.}
|
14
|
+
s.email = %q{contact@verticonaut.me}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
".rvmrc",
|
22
|
+
"LICENSE",
|
23
|
+
"README.rdoc",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"ar-audit-tracer.gemspec",
|
27
|
+
"lib/ar-audit-tracer.rb",
|
28
|
+
"lib/concern/audit/author.rb",
|
29
|
+
"test/concern/audit/author_test.rb",
|
30
|
+
"test/helper.rb",
|
31
|
+
"test/resources/models.rb",
|
32
|
+
"test/resources/schema.rb",
|
33
|
+
"test/test_ar-audit-tracer.rb"
|
34
|
+
]
|
35
|
+
s.homepage = %q{http://github.com/verticonaut/ar-audit-tracer}
|
36
|
+
s.require_paths = ["lib"]
|
37
|
+
s.rubygems_version = %q{1.3.7}
|
38
|
+
s.summary = %q{Track creator/modifiers of you AR Models similar to timestamps.}
|
39
|
+
s.test_files = [
|
40
|
+
"test/concern/audit/author_test.rb",
|
41
|
+
"test/helper.rb",
|
42
|
+
"test/resources/models.rb",
|
43
|
+
"test/resources/schema.rb",
|
44
|
+
"test/test_ar-audit-tracer.rb"
|
45
|
+
]
|
46
|
+
|
47
|
+
if s.respond_to? :specification_version then
|
48
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
49
|
+
s.specification_version = 3
|
50
|
+
|
51
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
52
|
+
else
|
53
|
+
end
|
54
|
+
else
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'concern/audit/author'
|
2
|
+
|
3
|
+
# ActiveRecordAuthors
|
4
|
+
module ActiveRecord
|
5
|
+
module ConnectionAdapters
|
6
|
+
|
7
|
+
class TableDefinition
|
8
|
+
|
9
|
+
# Creates author columns ...
|
10
|
+
#
|
11
|
+
# @param Symbol type The desired type for the columns, defaults to :string
|
12
|
+
# @param Hash *args Column options from rails
|
13
|
+
def authors(type=:string, *args)
|
14
|
+
options = args.extract_options!
|
15
|
+
column(:created_by, type, options)
|
16
|
+
column(:updated_by, type, options)
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
class Table
|
23
|
+
# Adds author (created_by and updated_by) columns to the table
|
24
|
+
# ===== Example
|
25
|
+
# t.authors
|
26
|
+
#
|
27
|
+
# @param Symbol type The desired type for the columns, defaults to :string
|
28
|
+
# @see SchemaStatements#add_authors
|
29
|
+
def authors(type=:string)
|
30
|
+
@base.add_authors(@table_name, type)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Removes the author columns (created_by and updated_by) from the table.
|
34
|
+
# ===== Example
|
35
|
+
# t.remove_authors
|
36
|
+
def remove_authors
|
37
|
+
@base.remove_authors(@table_name)
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
module SchemaStatements
|
43
|
+
# Adds author columns (created_by and updated_by) to the named table.
|
44
|
+
# ===== Examples
|
45
|
+
# add_authors(:suppliers)
|
46
|
+
def add_authors(table_name, type=:string)
|
47
|
+
add_column table_name, :created_by, type
|
48
|
+
add_column table_name, :updated_by, type
|
49
|
+
end
|
50
|
+
|
51
|
+
# Removes the author columns (created_by and updated_by) from the table definition.
|
52
|
+
# ===== Examples
|
53
|
+
# remove_authors(:suppliers)
|
54
|
+
def remove_authors(table_name)
|
55
|
+
remove_column table_name, :updated_by
|
56
|
+
remove_column table_name, :created_by
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
# = Active Record Author
|
63
|
+
#
|
64
|
+
# Active Record automatically authors create and update operations if the
|
65
|
+
# table has fields named <tt>created_by</tt> or
|
66
|
+
# <tt>updated_by</tt>.
|
67
|
+
#
|
68
|
+
# Authoring can be turned off by setting:
|
69
|
+
#
|
70
|
+
# <tt>ActiveRecord::Base.record_authors = false</tt>
|
71
|
+
module Author
|
72
|
+
extend ActiveSupport::Concern
|
73
|
+
|
74
|
+
included do
|
75
|
+
class_inheritable_accessor :record_authors, :instance_writer => false
|
76
|
+
self.record_authors = true
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
def create #:nodoc:
|
82
|
+
if record_authors
|
83
|
+
current_author = Concern::Audit::Author.current
|
84
|
+
|
85
|
+
all_author_attributes.each do |column|
|
86
|
+
write_attribute(column.to_s, current_author) if respond_to?(column) && self.send(column).nil?
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
super
|
91
|
+
end
|
92
|
+
|
93
|
+
def update(*args) #:nodoc:
|
94
|
+
if should_record_authors?
|
95
|
+
current_author = Concern::Audit::Author.current
|
96
|
+
|
97
|
+
author_attributes_for_update_in_model.each do |column|
|
98
|
+
column = column.to_s
|
99
|
+
next if attribute_changed?(column)
|
100
|
+
write_attribute(column, current_author)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
super
|
104
|
+
end
|
105
|
+
|
106
|
+
def should_record_authors?
|
107
|
+
record_authors && (!partial_updates? || changed?)
|
108
|
+
end
|
109
|
+
|
110
|
+
def author_attributes_for_update_in_model
|
111
|
+
author_attributes_for_update.select { |c| respond_to?(c) }
|
112
|
+
end
|
113
|
+
|
114
|
+
def author_attributes_for_update #:nodoc:
|
115
|
+
[:updated_by]
|
116
|
+
end
|
117
|
+
|
118
|
+
def author_attributes_for_create #:nodoc:
|
119
|
+
[:created_by]
|
120
|
+
end
|
121
|
+
|
122
|
+
def all_author_attributes #:nodoc:
|
123
|
+
author_attributes_for_create + author_attributes_for_update
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
|
128
|
+
Base.class_eval do
|
129
|
+
include Author
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require File.expand_path('../../../test_helper.rb', __FILE__)
|
3
|
+
|
4
|
+
# Test Thread.current stuff.
|
5
|
+
class Concern::Audit::AuthorTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
Concern::Audit::Author.current = nil
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_author_setting_in_single_thread
|
12
|
+
Concern::Audit::Author.current
|
13
|
+
|
14
|
+
assert_nil Concern::Audit::Author.current
|
15
|
+
Concern::Audit::Author.current="the_author"
|
16
|
+
|
17
|
+
assert_equal("the_author", Concern::Audit::Author.current)
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_author_setting_in_different_threads
|
21
|
+
Concern::Audit::Author.current="outer_thread"
|
22
|
+
|
23
|
+
assert_equal("outer_thread", Concern::Audit::Author.current)
|
24
|
+
|
25
|
+
t = Thread.fork do
|
26
|
+
assert_nil Concern::Audit::Author.current
|
27
|
+
|
28
|
+
Concern::Audit::Author.current="in_thread"
|
29
|
+
|
30
|
+
assert_equal("in_thread", Concern::Audit::Author.current)
|
31
|
+
end
|
32
|
+
|
33
|
+
# check if outer thread has still original value
|
34
|
+
t.join
|
35
|
+
assert_equal("outer_thread", Concern::Audit::Author.current)
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'fileutils'
|
4
|
+
require "active_record"
|
5
|
+
require 'logger'
|
6
|
+
|
7
|
+
# ------------------------------------------------------
|
8
|
+
# Setup AR environment
|
9
|
+
# ------------------------------------------------------
|
10
|
+
|
11
|
+
# Define connection info
|
12
|
+
ActiveRecord::Base.configurations = {
|
13
|
+
"test" => {
|
14
|
+
:adapter => 'sqlite3',
|
15
|
+
:database => ':memory:'
|
16
|
+
}
|
17
|
+
}
|
18
|
+
ActiveRecord::Base.establish_connection("test")
|
19
|
+
|
20
|
+
# Setup logger
|
21
|
+
tmp = File.expand_path('../../tmp', __FILE__)
|
22
|
+
FileUtils.mkdir_p(tmp)
|
23
|
+
ActiveRecord::Base.logger = Logger.new("#{tmp}/debug.log")
|
24
|
+
|
25
|
+
|
26
|
+
# ------------------------------------------------------
|
27
|
+
# Inject audit-trascer
|
28
|
+
# and setup test schema
|
29
|
+
# and define models used in tests
|
30
|
+
# ------------------------------------------------------
|
31
|
+
require "ar-audit-tracer"
|
32
|
+
|
33
|
+
require "resources/schema.rb"
|
34
|
+
require "resources/models.rb"
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# ------------------------------------------------------
|
2
|
+
# Defined the migrations
|
3
|
+
# ------------------------------------------------------
|
4
|
+
ActiveRecord::Schema.define(:version => 0) do
|
5
|
+
|
6
|
+
create_table :with_string_authors, :force => true do |t|
|
7
|
+
t.string :name
|
8
|
+
t.authors
|
9
|
+
end
|
10
|
+
|
11
|
+
create_table :with_integer_authors, :force => true do |t|
|
12
|
+
t.string :name
|
13
|
+
t.authors(:integer)
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestArAuditTracer < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
Concern::Audit::Author.current=nil
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_author_attributes_available
|
10
|
+
# test :string coded authors
|
11
|
+
assert WithStringAuthor.columns_hash.key? 'created_by'
|
12
|
+
assert WithStringAuthor.columns_hash.key? 'updated_by'
|
13
|
+
|
14
|
+
# test :string coded authors
|
15
|
+
assert WithIntegerAuthor.columns_hash.key? 'created_by'
|
16
|
+
assert WithIntegerAuthor.columns_hash.key? 'updated_by'
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_author_attributes_have_correct_type
|
20
|
+
# test :string coded authors
|
21
|
+
assert_equal(WithStringAuthor.columns_hash['created_by'].type, :string)
|
22
|
+
assert_equal(WithStringAuthor.columns_hash['updated_by'].type, :string)
|
23
|
+
|
24
|
+
# test :string coded authors
|
25
|
+
assert_equal(WithIntegerAuthor.columns_hash['created_by'].type, :integer)
|
26
|
+
assert_equal(WithIntegerAuthor.columns_hash['updated_by'].type, :integer)
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_author_setting_on_create
|
30
|
+
# test :string coded authors
|
31
|
+
Concern::Audit::Author.current="creator"
|
32
|
+
audited_record = WithStringAuthor.create!
|
33
|
+
|
34
|
+
assert_equal audited_record.created_by, "creator"
|
35
|
+
assert_equal audited_record.updated_by, "creator"
|
36
|
+
|
37
|
+
# test :integer coded authors
|
38
|
+
Concern::Audit::Author.current= 1
|
39
|
+
audited_record = WithIntegerAuthor.create!
|
40
|
+
|
41
|
+
assert_equal audited_record.created_by, 1
|
42
|
+
assert_equal audited_record.updated_by, 1
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_string_author_setting_on_update
|
46
|
+
Concern::Audit::Author.current="creator"
|
47
|
+
audited_record = WithStringAuthor.create!
|
48
|
+
|
49
|
+
assert_equal audited_record.created_by, "creator"
|
50
|
+
assert_equal audited_record.updated_by, "creator"
|
51
|
+
|
52
|
+
Concern::Audit::Author.current="updater"
|
53
|
+
audited_record.update_attribute(:name, "some_name")
|
54
|
+
|
55
|
+
assert_equal audited_record.created_by, "creator"
|
56
|
+
assert_equal audited_record.updated_by, "updater"
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_integer_author_setting_on_update
|
60
|
+
Concern::Audit::Author.current= 1
|
61
|
+
audited_record = WithStringAuthor.create!
|
62
|
+
|
63
|
+
assert_equal audited_record.created_by, 1
|
64
|
+
assert_equal audited_record.updated_by, 1
|
65
|
+
|
66
|
+
Concern::Audit::Author.current= 2
|
67
|
+
audited_record.update_attribute(:name, "some_name")
|
68
|
+
|
69
|
+
assert_equal audited_record.created_by, 1
|
70
|
+
assert_equal audited_record.updated_by, 2
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_string_author_with_ignored_save
|
74
|
+
Concern::Audit::Author.current= "creator"
|
75
|
+
audited_record = WithStringAuthor.create!
|
76
|
+
assert_equal audited_record.updated_by, "creator"
|
77
|
+
|
78
|
+
Concern::Audit::Author.current= "updater"
|
79
|
+
audited_record.save # save is not executed - there is nothing changed
|
80
|
+
assert_equal audited_record.updated_by, "creator"
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_integer_author_with_ignored_save
|
84
|
+
Concern::Audit::Author.current= 1
|
85
|
+
audited_record = WithStringAuthor.create!
|
86
|
+
assert_equal audited_record.updated_by, 1
|
87
|
+
|
88
|
+
Concern::Audit::Author.current= 2
|
89
|
+
audited_record.save # save is not executed - there is nothing changed
|
90
|
+
assert_equal audited_record.updated_by, 1
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
metadata
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ar-audit-tracer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
version: 0.1.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Martin Schweizer
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-11-27 00:00:00 +01:00
|
18
|
+
default_executable:
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: Handles ActiveRecord authors in the same way as timstamps.
|
22
|
+
email: contact@verticonaut.me
|
23
|
+
executables: []
|
24
|
+
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files:
|
28
|
+
- LICENSE
|
29
|
+
- README.rdoc
|
30
|
+
files:
|
31
|
+
- .document
|
32
|
+
- .rvmrc
|
33
|
+
- LICENSE
|
34
|
+
- README.rdoc
|
35
|
+
- Rakefile
|
36
|
+
- VERSION
|
37
|
+
- ar-audit-tracer.gemspec
|
38
|
+
- lib/ar-audit-tracer.rb
|
39
|
+
- lib/concern/audit/author.rb
|
40
|
+
- test/concern/audit/author_test.rb
|
41
|
+
- test/helper.rb
|
42
|
+
- test/resources/models.rb
|
43
|
+
- test/resources/schema.rb
|
44
|
+
- test/test_ar-audit-tracer.rb
|
45
|
+
has_rdoc: true
|
46
|
+
homepage: http://github.com/verticonaut/ar-audit-tracer
|
47
|
+
licenses: []
|
48
|
+
|
49
|
+
post_install_message:
|
50
|
+
rdoc_options: []
|
51
|
+
|
52
|
+
require_paths:
|
53
|
+
- lib
|
54
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
segments:
|
60
|
+
- 0
|
61
|
+
version: "0"
|
62
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
segments:
|
68
|
+
- 0
|
69
|
+
version: "0"
|
70
|
+
requirements: []
|
71
|
+
|
72
|
+
rubyforge_project:
|
73
|
+
rubygems_version: 1.3.7
|
74
|
+
signing_key:
|
75
|
+
specification_version: 3
|
76
|
+
summary: Track creator/modifiers of you AR Models similar to timestamps.
|
77
|
+
test_files:
|
78
|
+
- test/concern/audit/author_test.rb
|
79
|
+
- test/helper.rb
|
80
|
+
- test/resources/models.rb
|
81
|
+
- test/resources/schema.rb
|
82
|
+
- test/test_ar-audit-tracer.rb
|