centro / tracktor
- Source
- Commits
- Network (1)
- Issues (0)
- Downloads (0)
- Wiki (1)
- Graphs
-
Branch:
master
| name | age | message | |
|---|---|---|---|
| |
.gitignore | Tue Jun 09 05:44:57 -0700 2009 | |
| |
MIT-LICENSE | Tue Aug 19 13:45:52 -0700 2008 | |
| |
README.rdoc | Fri Feb 13 08:34:40 -0800 2009 | |
| |
Rakefile | Tue Aug 19 13:45:52 -0700 2008 | |
| |
init.rb | Wed Aug 12 18:31:09 -0700 2009 | |
| |
install.rb | Tue Aug 19 13:45:52 -0700 2008 | |
| |
lib/ | Tue Nov 17 15:02:05 -0800 2009 | |
| |
tasks/ | Tue Aug 19 13:45:52 -0700 2008 | |
| |
test/ | Tue Jun 09 08:04:04 -0700 2009 |
Tracktor
Tracktor is a Rails plugin that eases audit logging of actors (creator and updater) for any class that descends from ActiveRecord::Base. The goal is to seamlessly log the actors without needing to explicitly mention them when writing your application code. This is accomplished by storing the current actor in a thread-local variable for the duration of a particular HTTP request (note that this means that Tracktor will not work with multi-threaded application servers).
Any time you create or update a record within the context of a request, an ActiveRecord::Observer takes over and sets the creator and updater automatically. In other words:
# before - app/controllers/books_controller.rb
def create
@book = Book.create(params[:book].merge(:creator => current_user, :updater => current_user))
end
# after - app/controllers/books_controller.rb
def create
@book = Book.create(params[:book])
end
The simplest setup for Tracktor is as follows:
# app/models/book.rb (repeat with every model class for which you'd like automatic actor tracking)
class Book < ActiveRecord::Base
track_actors
end
# db/migrate/001_create_books.rb
class CreateBooks < ActiveRecord::Migration
def self.up
create_table :books do |t|
t.actors
end
end
end
# app/controllers/application.rb
class ApplicationController < ActionController::Base
enable_actor_tracking
end
Models
Tracktor adds an ActiveRecord::Base.track_actors method that sets up automatic actor tracking for the class. By default, Tracktor assumes that the actor’s class name is "User"; if this is not the case, you can specify the class name like so:
class Book < ActiveRecord::Base
track_actors :class_name => "Member"
end
You can also specify a default actor, which will be used if there is no current actor set:
class Book < ActiveRecord::Base
track_actors :default => lambda { User.find_by_id(0) }
end
Specifying track_actors will allow you to reference the creator and updater associations from the object being tracked:
book = Book.create!(:name => "Survivor") puts book.creator
Migrations
Tracktor adds an ActiveRecord::Migration#actors method that creates two integer columns: creator_id and updater_id. These columns reference the row ids of the actors that created or updated the book.
By default, these columns have not-null constraints (:null => false), but this may be overridden if desired. No foreign keys are created; if you care about that sort of thing, make sure you include it in your migration.
Controllers
Tracktor adds an ActionController::Base.enable_actor_tracking method, which should be added to application.rb after any before_filter or other code that is responsible for logging users in. This method wraps the request such that the current actor is available to an Observer that watches for record creation or updating.
By default, the enable_actor_tracking method will try to grab the actor by calling the current_user method; this can be overridden like so:
enable_actor_tracking :from => :logged_in_user
Testing
Tracktor hearts Test-Driven Development. In fact, Tracktor hearts TDD so much that it adds a Test::Unit::TestCase.test_actor_tracking_for method that can be used like so:
class BookTest < Test::Unit::TestCase
test_actor_tracking_for :book
end
This will create and run the following tests:
- test_creator_association
- test_updater_association
- test_creator_should_be_set_to_current_before_validation_on_create
- test_updater_should_be_set_to_current_before_validation
- test_creator_should_default_when_current_is_not_set
- test_updater_should_default_when_current_is_not_set
Any other tests you’d like to write (to test custom class names, etc.) are on you.
If you’re using Shoulda by ThoughtBot, you can instead use the Shoulda macro, like so:
class BookTest < Test::Unit::TestCase
context "an existing book"
setup { @book = Book.create! }
should_track_actors_for :book
end
end
This will create the appropriate shoulds.
Etc.
There are times when it is necessary to create/update objects that normally track actors when you are outside of the context of an HTTP request (or inside one without a logged in user). For this, Tracktor includes the as_actor method, which can be used like so:
as_actor(User.find_by_id(0)) do
Book.create!(:name => "Choke")
end
This can be especially useful when writing tests, command-line scripts, rake tasks, etc. Tracktor adds validations to creator_id and updater_id, so an error that states "Updated by can’t be blank" will often point to the fact that you are operating outside the context of an HTTP request, and need to use as_actor.
Copyright © 2008 Centro, released under the MIT license. Authored by:
