trackable 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/MIT-LICENSE +20 -0
- data/README +13 -0
- data/README.textile +1 -0
- data/Rakefile +40 -0
- data/VERSION +1 -0
- data/generators/trackable_migration/templates/migration.rb +17 -0
- data/generators/trackable_migration/trackable_migration_generator.rb +11 -0
- data/init.rb +2 -0
- data/install.rb +1 -0
- data/lib/trackable/acts_as_trackable.rb +32 -0
- data/lib/trackable/event.rb +23 -0
- data/lib/trackable.rb +29 -0
- data/rails/init.rb +1 -0
- data/tasks/acts_as_eventable_tasks.rake +4 -0
- data/test/database.yml +3 -0
- data/test/migration_test.rb +33 -0
- data/test/models.rb +15 -0
- data/test/schema.rb +25 -0
- data/test/test_helper.rb +37 -0
- data/test/trackable_controller_test.rb +56 -0
- data/test/trackable_test.rb +131 -0
- data/uninstall.rb +1 -0
- metadata +99 -0
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright (c) 2010 [name of plugin creator]
|
|
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
ADDED
data/README.textile
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
h2. acts_as_eventable
|
data/Rakefile
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require 'rake'
|
|
2
|
+
require 'rake/testtask'
|
|
3
|
+
require 'rake/rdoctask'
|
|
4
|
+
|
|
5
|
+
begin
|
|
6
|
+
require 'jeweler'
|
|
7
|
+
Jeweler::Tasks.new do |gem|
|
|
8
|
+
gem.name = "trackable"
|
|
9
|
+
gem.summary = %Q{Add a readable event history to your models}
|
|
10
|
+
gem.description = %Q{Add a readable event history to your models}
|
|
11
|
+
gem.email = "jim@jimvanfleet.com"
|
|
12
|
+
gem.homepage = "http://github.com/bigfleet/trackable"
|
|
13
|
+
gem.authors = ["bigfleet"]
|
|
14
|
+
gem.add_development_dependency "ruby-sqlite", ">= 0"
|
|
15
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
|
16
|
+
end
|
|
17
|
+
Jeweler::GemcutterTasks.new
|
|
18
|
+
rescue LoadError
|
|
19
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
desc 'Default: run unit tests.'
|
|
23
|
+
task :default => :test
|
|
24
|
+
|
|
25
|
+
desc 'Test the acts_as_eventable plugin.'
|
|
26
|
+
Rake::TestTask.new(:test) do |t|
|
|
27
|
+
t.libs << 'lib'
|
|
28
|
+
t.libs << 'test'
|
|
29
|
+
t.pattern = 'test/**/*_test.rb'
|
|
30
|
+
t.verbose = true
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
desc 'Generate documentation for the acts_as_eventable plugin.'
|
|
34
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
|
35
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
36
|
+
rdoc.title = 'Trackable'
|
|
37
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
|
38
|
+
rdoc.rdoc_files.include('README')
|
|
39
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
40
|
+
end
|
data/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.1.0
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
class TrackableMigration < ActiveRecord::Migration
|
|
2
|
+
def self.up
|
|
3
|
+
create_table :events do |t|
|
|
4
|
+
t.string :eventable_type, :null => false
|
|
5
|
+
t.integer :eventable_id, :null => false
|
|
6
|
+
t.string :field_name, :null => false
|
|
7
|
+
t.string :whodunnit
|
|
8
|
+
t.string :message
|
|
9
|
+
t.datetime :created_at
|
|
10
|
+
end
|
|
11
|
+
add_index :events, [:eventable_id, :eventable_type, :field_name]
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def self.down
|
|
15
|
+
drop_table :events
|
|
16
|
+
end
|
|
17
|
+
end
|
data/init.rb
ADDED
data/install.rb
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Install hook code here
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module ActsAsTrackable
|
|
2
|
+
def self.included(base)
|
|
3
|
+
base.send :extend, ClassMethods
|
|
4
|
+
base.instance_eval{
|
|
5
|
+
cattr_accessor :eventable_options
|
|
6
|
+
}
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
module ClassMethods
|
|
10
|
+
|
|
11
|
+
def trackable(options)
|
|
12
|
+
instance_eval{
|
|
13
|
+
self.eventable_options = options
|
|
14
|
+
}
|
|
15
|
+
send :include, InstanceMethods
|
|
16
|
+
has_many :events, :as => :eventable, :dependent => :destroy, :order => "created_at desc"
|
|
17
|
+
after_save :record_events
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
module InstanceMethods
|
|
22
|
+
def record_events
|
|
23
|
+
active_keys = changes.keys.reject{ |key| %w{id created_at updated_at}.include?(key)}
|
|
24
|
+
active_keys.map do |key|
|
|
25
|
+
old_val, new_val = changes[key]
|
|
26
|
+
events.create(Event.attributes_from(self, key, old_val, new_val))
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
ActiveRecord::Base.send :include, ActsAsTrackable
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
class Event < ActiveRecord::Base
|
|
2
|
+
|
|
3
|
+
def self.attributes_from(model, key, old_val, new_val)
|
|
4
|
+
eventable_options = model.class.eventable_options
|
|
5
|
+
msg = if eventable_options[:events][key.to_sym] && eventable_options[:events][key.to_sym][new_val]
|
|
6
|
+
eventable_options[:events][key.to_sym][new_val]
|
|
7
|
+
elsif eventable_options[:events][key.to_sym] && eventable_options[:events][key.to_sym][:message]
|
|
8
|
+
the_proc = eventable_options[:events][key.to_sym][:message]
|
|
9
|
+
if key.index("_id") # hackish, but this is a convention
|
|
10
|
+
reference = key[0..-4].to_sym
|
|
11
|
+
the_proc.call(model.send(reference).to_s)
|
|
12
|
+
else
|
|
13
|
+
the_proc.call(new_val)
|
|
14
|
+
end
|
|
15
|
+
elsif key.index("_id") # hackish, but this is a convention
|
|
16
|
+
reference = key[0..-4].to_sym
|
|
17
|
+
"#{key.titleize} changed to #{model.send(reference).to_s}"
|
|
18
|
+
else
|
|
19
|
+
"#{key.titleize} changed to #{new_val}"
|
|
20
|
+
end
|
|
21
|
+
{:field_name => key, :message => msg, :whodunnit => Trackable.whodunnit}
|
|
22
|
+
end
|
|
23
|
+
end
|
data/lib/trackable.rb
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Trackable
|
|
2
|
+
require 'trackable/acts_as_trackable'
|
|
3
|
+
require 'trackable/event'
|
|
4
|
+
|
|
5
|
+
module Trackable
|
|
6
|
+
@@whodunnit = nil
|
|
7
|
+
|
|
8
|
+
def self.included(base)
|
|
9
|
+
base.before_filter :set_whodunnit
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.whodunnit
|
|
13
|
+
@@whodunnit.respond_to?(:call) ? @@whodunnit.call : @@whodunnit
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.whodunnit=(value)
|
|
17
|
+
@@whodunnit = value
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def set_whodunnit
|
|
23
|
+
@@whodunnit = lambda {
|
|
24
|
+
self.send :current_user rescue nil
|
|
25
|
+
}
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
ActionController::Base.send :include, Trackable
|
data/rails/init.rb
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), '/../lib/trackable')
|
data/test/database.yml
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper.rb'
|
|
2
|
+
require 'rails_generator'
|
|
3
|
+
require 'rails_generator/scripts/generate'
|
|
4
|
+
|
|
5
|
+
class MigrationTest < Test::Unit::TestCase
|
|
6
|
+
|
|
7
|
+
def setup
|
|
8
|
+
FileUtils.mkdir_p(fake_rails_root)
|
|
9
|
+
@original_files = file_list
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def teardown
|
|
13
|
+
ActiveRecord::Base.pluralize_table_names = true
|
|
14
|
+
FileUtils.rm_r(fake_rails_root)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def test_generates_correct_file_name
|
|
18
|
+
Rails::Generator::Scripts::Generate.new.run(["trackable_migration"], :destination => fake_rails_root)
|
|
19
|
+
new_file = (file_list - @original_files).first
|
|
20
|
+
assert_match /trackable_migration/, new_file
|
|
21
|
+
assert File.read(new_file) =~ /create_table :events do |t|/
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
def fake_rails_root
|
|
26
|
+
File.join(File.dirname(__FILE__), 'rails_root')
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def file_list
|
|
30
|
+
Dir.glob(File.join(fake_rails_root, "db", "migrate", "*"))
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
data/test/models.rb
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
class Foo < ActiveRecord::Base
|
|
2
|
+
trackable :events =>{
|
|
3
|
+
:no_homers => {true => "Homers have been barred.", false => "Homers have been allowed."},
|
|
4
|
+
:custom_status => {:message => Proc.new {|n| "The value of a custom string field changed to #{n}" }},
|
|
5
|
+
:custom_bar_id => {:message => Proc.new{|n| "Active Bar set to #{n}"}}
|
|
6
|
+
}
|
|
7
|
+
belongs_to :bar, :class_name => "Bar"
|
|
8
|
+
belongs_to :custom_bar, :class_name => "Bar"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class Bar < ActiveRecord::Base
|
|
12
|
+
def to_s
|
|
13
|
+
name
|
|
14
|
+
end
|
|
15
|
+
end
|
data/test/schema.rb
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
ActiveRecord::Schema.define(:version => 0) do
|
|
2
|
+
create_table :foos, :force => true do |t|
|
|
3
|
+
t.boolean :no_homers
|
|
4
|
+
t.string :status
|
|
5
|
+
t.string :custom_status
|
|
6
|
+
t.integer :bar_id
|
|
7
|
+
t.integer :custom_bar_id
|
|
8
|
+
|
|
9
|
+
t.timestamps
|
|
10
|
+
end
|
|
11
|
+
create_table :bars, :force => true do |t|
|
|
12
|
+
t.string :name
|
|
13
|
+
|
|
14
|
+
t.timestamps
|
|
15
|
+
end
|
|
16
|
+
# This is the active table
|
|
17
|
+
create_table :events, :force => true do |t|
|
|
18
|
+
t.string :eventable_type, :null => false
|
|
19
|
+
t.integer :eventable_id, :null => false
|
|
20
|
+
t.string :field_name, :null => false
|
|
21
|
+
t.string :whodunnit
|
|
22
|
+
t.string :message
|
|
23
|
+
t.datetime :created_at
|
|
24
|
+
end
|
|
25
|
+
end
|
data/test/test_helper.rb
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
ENV['RAILS_ENV'] = 'test'
|
|
2
|
+
ENV['RAILS_ROOT'] ||= File.dirname(__FILE__) + '/../../../..'
|
|
3
|
+
|
|
4
|
+
require 'rubygems'
|
|
5
|
+
require 'test/unit'
|
|
6
|
+
|
|
7
|
+
require File.expand_path(File.join(ENV['RAILS_ROOT'], 'config/environment.rb'))
|
|
8
|
+
require 'models'
|
|
9
|
+
|
|
10
|
+
def load_schema
|
|
11
|
+
config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
|
|
12
|
+
ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
|
|
13
|
+
|
|
14
|
+
db_adapter = ENV['DB']
|
|
15
|
+
|
|
16
|
+
# no db passed, try one of these fine config-free DBs before bombing.
|
|
17
|
+
db_adapter ||=
|
|
18
|
+
begin
|
|
19
|
+
require 'rubygems'
|
|
20
|
+
require 'sqlite'
|
|
21
|
+
'sqlite'
|
|
22
|
+
rescue MissingSourceFile
|
|
23
|
+
begin
|
|
24
|
+
require 'sqlite3'
|
|
25
|
+
'sqlite3'
|
|
26
|
+
rescue MissingSourceFile
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
if db_adapter.nil?
|
|
31
|
+
raise "No DB Adapter selected. Pass the DB= option to pick one, or install Sqlite or Sqlite3."
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
ActiveRecord::Base.establish_connection(config[db_adapter])
|
|
35
|
+
load(File.dirname(__FILE__) + "/schema.rb")
|
|
36
|
+
require File.dirname(__FILE__) + '/../init.rb'
|
|
37
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper.rb'
|
|
2
|
+
|
|
3
|
+
class ApplicationController < ActionController::Base
|
|
4
|
+
def rescue_action(e)
|
|
5
|
+
raise e
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
# Returns id of hypothetical current user
|
|
9
|
+
def current_user
|
|
10
|
+
153
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class FoosController < ApplicationController
|
|
15
|
+
def create
|
|
16
|
+
@foo = Foo.create params[:foo]
|
|
17
|
+
head :ok
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def update
|
|
21
|
+
@foo = Foo.find params[:id]
|
|
22
|
+
@foo.update_attributes params[:foo]
|
|
23
|
+
head :ok
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class TrackableControllerTest < ActionController::TestCase #Test::Unit::TestCase
|
|
29
|
+
def setup
|
|
30
|
+
@controller = FoosController.new
|
|
31
|
+
@request = ActionController::TestRequest.new
|
|
32
|
+
@response = ActionController::TestResponse.new
|
|
33
|
+
|
|
34
|
+
ActionController::Routing::Routes.draw do |map|
|
|
35
|
+
map.resources :foos
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
test 'create' do
|
|
40
|
+
post :create, :foo => { :status => 'Flugel' }
|
|
41
|
+
foo = assigns(:foo)
|
|
42
|
+
assert_equal 1, foo.events.length
|
|
43
|
+
assert_equal 153, foo.events.last.whodunnit.to_i
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
test 'update' do
|
|
47
|
+
w = Foo.create :status => 'Duvel'
|
|
48
|
+
assert_equal 1, w.events.length
|
|
49
|
+
put :update, :id => w.id, :foo => { :status => 'Bugle' }
|
|
50
|
+
foo = assigns(:foo)
|
|
51
|
+
assert_equal 2, foo.events.length
|
|
52
|
+
assert_equal 153, foo.events.last.whodunnit.to_i
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
end
|
|
56
|
+
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
class TrackableTest < Test::Unit::TestCase
|
|
4
|
+
|
|
5
|
+
load_schema
|
|
6
|
+
|
|
7
|
+
def test_schema_has_loaded_correctly
|
|
8
|
+
Foo.create
|
|
9
|
+
Bar.create
|
|
10
|
+
assert Foo.count >= 1
|
|
11
|
+
assert Bar.count >= 1
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def test_cattr_accessor_installed
|
|
15
|
+
assert_not_nil Foo.eventable_options
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def test_desired_boolean_change_trigger
|
|
19
|
+
foo = Foo.create
|
|
20
|
+
foo.update_attribute(:no_homers, true)
|
|
21
|
+
assert_equal 1, foo.events.size
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def test_desired_boolean_messaging
|
|
25
|
+
foo = Foo.create
|
|
26
|
+
foo.update_attribute(:no_homers, true)
|
|
27
|
+
assert_equal "Homers have been barred.", foo.events.first.message
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def test_desired_boolean_messaging_stackable
|
|
31
|
+
foo = Foo.create
|
|
32
|
+
foo.update_attribute(:no_homers, true)
|
|
33
|
+
sleep 1 #mur
|
|
34
|
+
foo.update_attribute(:no_homers, false)
|
|
35
|
+
assert_equal "Homers have been allowed.", foo.events.first.message
|
|
36
|
+
assert_equal "Homers have been barred.", foo.events.last.message
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def test_desired_string_change_trigger
|
|
40
|
+
foo = Foo.create
|
|
41
|
+
foo.update_attribute(:status, "New")
|
|
42
|
+
assert_equal 1, foo.events.size
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def test_desired_string_messaging
|
|
46
|
+
foo = Foo.create
|
|
47
|
+
foo.update_attribute(:status, "New")
|
|
48
|
+
assert_equal "Status changed to New", foo.events.first.message
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def test_desired_string_stackability
|
|
52
|
+
foo = Foo.create
|
|
53
|
+
foo.update_attribute(:status, "Old")
|
|
54
|
+
sleep 1 #mur
|
|
55
|
+
foo.update_attribute(:status, "New")
|
|
56
|
+
assert_equal "Status changed to New", foo.events.first.message
|
|
57
|
+
assert_equal "Status changed to Old", foo.events.last.message
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def test_desired_custom_string_change_trigger
|
|
61
|
+
foo = Foo.create
|
|
62
|
+
foo.update_attribute(:custom_status, "New")
|
|
63
|
+
assert_equal 1, foo.events.size
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def test_desired_custom_string_messaging
|
|
67
|
+
foo = Foo.create
|
|
68
|
+
foo.update_attribute(:custom_status, "New")
|
|
69
|
+
assert_equal "The value of a custom string field changed to New", foo.events.first.message
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def test_desired_custom_string_stackability
|
|
73
|
+
foo = Foo.create
|
|
74
|
+
foo.update_attribute(:custom_status, "Old")
|
|
75
|
+
sleep 1 #mur
|
|
76
|
+
foo.update_attribute(:custom_status, "New")
|
|
77
|
+
assert_equal "The value of a custom string field changed to New", foo.events.first.message
|
|
78
|
+
assert_equal "The value of a custom string field changed to Old", foo.events.last.message
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def test_desired_reference_change_trigger
|
|
82
|
+
foo = Foo.create
|
|
83
|
+
bar = Bar.create(:name => "Baloney")
|
|
84
|
+
foo.bar = bar; foo.save
|
|
85
|
+
assert_equal 1, foo.events.size
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def test_desired_reference_messaging
|
|
89
|
+
foo = Foo.create
|
|
90
|
+
bar = Bar.create(:name => "Baloney")
|
|
91
|
+
foo.bar = bar; foo.save
|
|
92
|
+
assert_equal "Bar changed to Baloney", foo.events.first.message
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def test_desired_reference_stackability
|
|
96
|
+
foo = Foo.create
|
|
97
|
+
bar1 = Bar.create(:name => "Peanut Butter")
|
|
98
|
+
bar2 = Bar.create(:name => "Jelly")
|
|
99
|
+
foo.bar = bar1; foo.save
|
|
100
|
+
sleep 1 #mur
|
|
101
|
+
foo.bar = bar2; foo.save
|
|
102
|
+
assert_equal "Bar changed to Jelly", foo.events.first.message
|
|
103
|
+
assert_equal "Bar changed to Peanut Butter", foo.events.last.message
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def test_desired_custom_reference_change_trigger
|
|
107
|
+
foo = Foo.create
|
|
108
|
+
bar = Bar.create(:name => "Baloney")
|
|
109
|
+
foo.custom_bar = bar; foo.save
|
|
110
|
+
assert_equal 1, foo.events.size
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def test_desired_custom_reference_messaging
|
|
114
|
+
foo = Foo.create
|
|
115
|
+
bar = Bar.create(:name => "Baloney")
|
|
116
|
+
foo.custom_bar = bar; foo.save
|
|
117
|
+
assert_equal "Active Bar set to Baloney", foo.events.first.message
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def test_desired_custom_reference_stackability
|
|
121
|
+
foo = Foo.create
|
|
122
|
+
bar1 = Bar.create(:name => "Peanut Butter")
|
|
123
|
+
bar2 = Bar.create(:name => "Jelly")
|
|
124
|
+
foo.custom_bar = bar1; foo.save
|
|
125
|
+
sleep 1 #mur
|
|
126
|
+
foo.custom_bar = bar2; foo.save
|
|
127
|
+
assert_equal "Active Bar set to Jelly", foo.events.first.message
|
|
128
|
+
assert_equal "Active Bar set to Peanut Butter", foo.events.last.message
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
end
|
data/uninstall.rb
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Uninstall hook code here
|
metadata
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: trackable
|
|
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
|
+
- bigfleet
|
|
13
|
+
autorequire:
|
|
14
|
+
bindir: bin
|
|
15
|
+
cert_chain: []
|
|
16
|
+
|
|
17
|
+
date: 2010-02-23 00:00:00 -05:00
|
|
18
|
+
default_executable:
|
|
19
|
+
dependencies:
|
|
20
|
+
- !ruby/object:Gem::Dependency
|
|
21
|
+
name: ruby-sqlite
|
|
22
|
+
prerelease: false
|
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
|
24
|
+
requirements:
|
|
25
|
+
- - ">="
|
|
26
|
+
- !ruby/object:Gem::Version
|
|
27
|
+
segments:
|
|
28
|
+
- 0
|
|
29
|
+
version: "0"
|
|
30
|
+
type: :development
|
|
31
|
+
version_requirements: *id001
|
|
32
|
+
description: Add a readable event history to your models
|
|
33
|
+
email: jim@jimvanfleet.com
|
|
34
|
+
executables: []
|
|
35
|
+
|
|
36
|
+
extensions: []
|
|
37
|
+
|
|
38
|
+
extra_rdoc_files:
|
|
39
|
+
- README
|
|
40
|
+
- README.textile
|
|
41
|
+
files:
|
|
42
|
+
- MIT-LICENSE
|
|
43
|
+
- README
|
|
44
|
+
- Rakefile
|
|
45
|
+
- VERSION
|
|
46
|
+
- generators/trackable_migration/templates/migration.rb
|
|
47
|
+
- generators/trackable_migration/trackable_migration_generator.rb
|
|
48
|
+
- init.rb
|
|
49
|
+
- install.rb
|
|
50
|
+
- lib/trackable.rb
|
|
51
|
+
- lib/trackable/acts_as_trackable.rb
|
|
52
|
+
- lib/trackable/event.rb
|
|
53
|
+
- rails/init.rb
|
|
54
|
+
- tasks/acts_as_eventable_tasks.rake
|
|
55
|
+
- test/database.yml
|
|
56
|
+
- test/models.rb
|
|
57
|
+
- test/schema.rb
|
|
58
|
+
- test/test_helper.rb
|
|
59
|
+
- test/trackable_controller_test.rb
|
|
60
|
+
- test/trackable_test.rb
|
|
61
|
+
- uninstall.rb
|
|
62
|
+
- README.textile
|
|
63
|
+
has_rdoc: true
|
|
64
|
+
homepage: http://github.com/bigfleet/trackable
|
|
65
|
+
licenses: []
|
|
66
|
+
|
|
67
|
+
post_install_message:
|
|
68
|
+
rdoc_options:
|
|
69
|
+
- --charset=UTF-8
|
|
70
|
+
require_paths:
|
|
71
|
+
- lib
|
|
72
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
73
|
+
requirements:
|
|
74
|
+
- - ">="
|
|
75
|
+
- !ruby/object:Gem::Version
|
|
76
|
+
segments:
|
|
77
|
+
- 0
|
|
78
|
+
version: "0"
|
|
79
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
80
|
+
requirements:
|
|
81
|
+
- - ">="
|
|
82
|
+
- !ruby/object:Gem::Version
|
|
83
|
+
segments:
|
|
84
|
+
- 0
|
|
85
|
+
version: "0"
|
|
86
|
+
requirements: []
|
|
87
|
+
|
|
88
|
+
rubyforge_project:
|
|
89
|
+
rubygems_version: 1.3.6
|
|
90
|
+
signing_key:
|
|
91
|
+
specification_version: 3
|
|
92
|
+
summary: Add a readable event history to your models
|
|
93
|
+
test_files:
|
|
94
|
+
- test/migration_test.rb
|
|
95
|
+
- test/models.rb
|
|
96
|
+
- test/schema.rb
|
|
97
|
+
- test/test_helper.rb
|
|
98
|
+
- test/trackable_controller_test.rb
|
|
99
|
+
- test/trackable_test.rb
|