Skip to content

Commit

Permalink
Move code around to allow for better separation of backends.
Browse files Browse the repository at this point in the history
  • Loading branch information
wvanbergen committed Feb 20, 2012
1 parent 46ee885 commit 0e5cf64
Show file tree
Hide file tree
Showing 11 changed files with 236 additions and 224 deletions.
13 changes: 1 addition & 12 deletions lib/state_machine/audit_trail.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,10 @@ module StateMachine::AuditTrail
def self.setup
StateMachine::Machine.send(:include, StateMachine::AuditTrail::TransitionAuditing)
end

# Public creates an instance of the class which does the actual logging
#
# transition_class: the Class which holds the audit trail
#
# in order to adda new ORM here, copy audit_trail/mongoid.rb to whatever you want to call the new file and implement the #log function there
# then, return from here the appropriate object based on which ORM the transition_class is using
def self.create_audit_trail_logger(transition_class)
return ActiveRecord.new(transition_class) if transition_class < ::ActiveRecord::Base # for ActiveRecord
return Mongoid.new(transition_class) if transition_class.included_modules.include?(::Mongoid::Document) # for Mongoid
raise NotImplemented, "Only support for ActiveRecord and Mongoid is included at this time"
end
end

require 'state_machine/audit_trail/transition_auditing'
require 'state_machine/audit_trail/backend'
require 'state_machine/audit_trail/railtie' if defined?(::Rails)

StateMachine::AuditTrail.setup
23 changes: 20 additions & 3 deletions lib/state_machine/audit_trail/backend.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,25 @@
class StateMachine::AuditTrail::Backend < Struct.new(:transition_class)

autoload :Mongoid, 'state_machine/audit_trail/backend/mongoid'
autoload :ActiveRecord, 'state_machine/audit_trail/backend/active_record'

def log(object, event, from, to, timestamp = Time.now)
raise NotImplemented, "Implement in a subclass."
end

# Public creates an instance of the class which does the actual logging
#
# transition_class: the Class which holds the audit trail
#
# in order to adda new ORM here, copy audit_trail/mongoid.rb to whatever you want to call the new file and implement the #log function there
# then, return from here the appropriate object based on which ORM the transition_class is using
def self.create_for_transition_class(transition_class)
if Object.const_defined?('ActiveRecord') && transition_class.ancestors.include?(::ActiveRecord::Base)
return StateMachine::AuditTrail::Backend::ActiveRecord.new(transition_class)
elsif Object.const_defined?('Mongoid') && transition_class.ancestors.include?(::Mongoid::Document)
return StateMachine::AuditTrail::Backend::Mongoid.new(transition_class)
else
raise NotImplemented, "Only support for ActiveRecord and Mongoid is included at this time"
end
end
end

require 'state_machine/audit_trail/active_record'
require 'state_machine/audit_trail/mongoid'
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
class StateMachine::AuditTrail::ActiveRecord < StateMachine::AuditTrail::Backend
class StateMachine::AuditTrail::Backend::ActiveRecord < StateMachine::AuditTrail::Backend

def log(object, event, from, to, timestamp = Time.now)
# Let ActiveRecord manage the timestamp for us so it does the
# right thing with regards to timezones.
Expand All @@ -9,4 +10,3 @@ def foreign_key_field(object)
object.class.base_class.name.foreign_key.to_sym
end
end

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# This is the class that does the actual logging.
# We need one of these per ORM

class StateMachine::AuditTrail::Mongoid < StateMachine::AuditTrail::Backend
class StateMachine::AuditTrail::Backend::Mongoid < StateMachine::AuditTrail::Backend

# Public writes the log to the database
#
Expand Down
2 changes: 1 addition & 1 deletion lib/state_machine/audit_trail/transition_auditing.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def store_audit_trail(options = {})

# Public returns an instance of the class which does the actual audit trail logging
def audit_trail
@transition_auditor ||= StateMachine::AuditTrail.create_audit_trail_logger(transition_class)
@transition_auditor ||= StateMachine::AuditTrail::Backend.create_for_transition_class(transition_class)
end

private
Expand Down
83 changes: 83 additions & 0 deletions spec/helpers/active_record.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
require 'active_record'

### Setup test database

ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => ':memory:')

ActiveRecord::Base.connection.create_table(:active_record_test_models) do |t|
t.string :state
t.string :type
t.timestamps
end

ActiveRecord::Base.connection.create_table(:active_record_test_model_with_multiple_state_machines) do |t|
t.string :first
t.string :second
t.timestamps
end

# We probably want to provide a generator for this model and the accompanying migration.
class ActiveRecordTestModelStateTransition < ActiveRecord::Base
belongs_to :test_model
end

class ActiveRecordTestModelWithMultipleStateMachinesFirstTransition < ActiveRecord::Base
belongs_to :test_model
end

class ActiveRecordTestModelWithMultipleStateMachinesSecondTransition < ActiveRecord::Base
belongs_to :test_model
end

class ActiveRecordTestModel < ActiveRecord::Base

state_machine :state, :initial => :waiting do # log initial state?
store_audit_trail

event :start do
transition [:waiting, :stopped] => :started
end

event :stop do
transition :started => :stopped
end
end
end

class ActiveRecordTestModelDescendant < ActiveRecordTestModel
end

class ActiveRecordTestModelWithMultipleStateMachines < ActiveRecord::Base

state_machine :first, :initial => :beginning do
store_audit_trail

event :begin_first do
transition :beginning => :end
end
end

state_machine :second do
store_audit_trail

event :begin_second do
transition nil => :beginning_second
end
end
end

def create_transition_table(owner_class, state)
class_name = "#{owner_class.name}#{state.to_s.camelize}Transition"

ActiveRecord::Base.connection.create_table(class_name.tableize) do |t|
t.integer owner_class.name.foreign_key
t.string :event
t.string :from
t.string :to
t.datetime :created_at
end
end

create_transition_table(ActiveRecordTestModel, :state)
create_transition_table(ActiveRecordTestModelWithMultipleStateMachines, :first)
create_transition_table(ActiveRecordTestModelWithMultipleStateMachines, :second)
31 changes: 10 additions & 21 deletions spec/spec_helper_mongoid.rb → spec/helpers/mongoid.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
require 'rubygems'
require 'bundler/setup'

require 'active_record'
require 'mongoid'
require 'rspec'
require 'state_machine/audit_trail'


### Setup test database

Expand All @@ -16,25 +9,25 @@


# We probably want to provide a generator for this model and the accompanying migration.
class TestModelStateTransition
class MongoidTestModelStateTransition
include Mongoid::Document
include Mongoid::Timestamps
belongs_to :test_model
belongs_to :mongoid_test_model
end

class TestModelWithMultipleStateMachinesFirstTransition
class MongoidTestModelWithMultipleStateMachinesFirstTransition
include Mongoid::Document
include Mongoid::Timestamps
belongs_to :test_model
belongs_to :mongoid_test_model
end

class TestModelWithMultipleStateMachinesSecondTransition
class MongoidTestModelWithMultipleStateMachinesSecondTransition
include Mongoid::Document
include Mongoid::Timestamps
belongs_to :test_model
belongs_to :mongoid_test_model
end

class TestModel
class MongoidTestModel

include Mongoid::Document
include Mongoid::Timestamps
Expand All @@ -52,11 +45,11 @@ class TestModel
end
end

class TestModelDescendant < TestModel
class MongoidTestModelDescendant < MongoidTestModel
include Mongoid::Timestamps
end

class TestModelWithMultipleStateMachines
class MongoidTestModelWithMultipleStateMachines

include Mongoid::Document
include Mongoid::Timestamps
Expand All @@ -73,11 +66,7 @@ class TestModelWithMultipleStateMachines
store_audit_trail

event :begin_second do
transition nil => :beginning
transition nil => :beginning_second
end
end
end


RSpec.configure do |config|
end
86 changes: 0 additions & 86 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,93 +2,7 @@
require 'bundler/setup'

require 'rspec'
require 'active_record'
require 'state_machine/audit_trail'


### Setup test database

ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => ':memory:')

ActiveRecord::Base.connection.create_table(:test_models) do |t|
t.string :state
t.string :type
t.timestamps
end

ActiveRecord::Base.connection.create_table(:test_model_with_multiple_state_machines) do |t|
t.string :first
t.string :second
t.timestamps
end


def create_transition_table(owner_class, state)
class_name = "#{owner_class.name}#{state.to_s.camelize}Transition"

ActiveRecord::Base.connection.create_table(class_name.tableize) do |t|
t.integer owner_class.name.foreign_key
t.string :event
t.string :from
t.string :to
t.datetime :created_at
end
end


# We probably want to provide a generator for this model and the accompanying migration.
class TestModelStateTransition < ActiveRecord::Base
belongs_to :test_model
end

class TestModelWithMultipleStateMachinesFirstTransition < ActiveRecord::Base
belongs_to :test_model
end

class TestModelWithMultipleStateMachinesSecondTransition < ActiveRecord::Base
belongs_to :test_model
end

class TestModel < ActiveRecord::Base

state_machine :state, :initial => :waiting do # log initial state?
store_audit_trail

event :start do
transition [:waiting, :stopped] => :started
end

event :stop do
transition :started => :stopped
end
end
end

class TestModelDescendant < TestModel
end

class TestModelWithMultipleStateMachines < ActiveRecord::Base

state_machine :first, :initial => :beginning do
store_audit_trail

event :begin_first do
transition :beginning => :end
end
end

state_machine :second do
store_audit_trail

event :begin_second do
transition nil => :beginning
end
end
end

create_transition_table(TestModel, :state)
create_transition_table(TestModelWithMultipleStateMachines, :first)
create_transition_table(TestModelWithMultipleStateMachines, :second)

RSpec.configure do |config|
end
Loading

0 comments on commit 0e5cf64

Please sign in to comment.