Skip to content

Instantly share code, notes, and snippets.

@michael
Created October 8, 2008 13:44
Show Gist options
  • Select an option

  • Save michael/15520 to your computer and use it in GitHub Desktop.

Select an option

Save michael/15520 to your computer and use it in GitHub Desktop.
# namestorming
# SteadyStateMachine
# Workflowable
# WorkflowEngine
module DataMapper
module Is
module PersistentStateMachine
class DmIsPersistentStateMachineException < Exception; end
def self.included(base)
base.extend ClassMethods
end
# -> FooStateTransition
module Transition
def self.included(base)
base.extend ClassMethods
end
include DataMapper::Resource
is :remixable
property :id, Integer, :key => true, :serial => true
property :guard, String
#belongs_to :quote_event
# alias event quote_event
# def event
# self.class
# # self.quote_event
# end
module ClassMethods
end
end
# -> FooState
module State
def self.included(base)
base.extend ClassMethods
end
include DataMapper::Resource
# def self.remix
# def id
property :id, Integer, :key => true, :serial => true
property :code, String
property :name, String, :length => 255
# not possible here, why??
# remix n, "DataMapper::Is::PersistentStateMachine::Transition", :as => "destinations", :for => 'self.name', :via => "target"
def events
evts = []
destinations.map do |transition|
# uses the generic event method
transition.event
end
end
module ClassMethods
end
end
# -> FooEvent
module Event
include DataMapper::Resource
property :id, Integer, :key => true, :serial => true
property :name, String
end
# this method is executed in the context of the base model on class level
def is_persistent_state_machine(options = {})
@is_persistent_state_machine = true
@prefix = options[:prefix] || self.name
attr_accessor :my_instance_var
# spielerei
@my_instance_var = "blaaah"
@@my_class_var = "blaaah"
# adds class and instance methods to the base class?
extend Forwardable
extend DataMapper::Is::PersistentStateMachine::ClassMethods
include DataMapper::Is::PersistentStateMachine::InstanceMethods
# new property that holds the foo_state_id
property Extlib::Inflection.foreign_key(@prefix+"State").to_sym, Integer
belongs_to Extlib::Inflection.underscore(@prefix+"State").to_sym
def_delegators :@state, :events, :destinations
DataMapper.logger.info "Loading PersistentStateMachine Plugin"
# will create FooState
@state_model = model_from_context(DataMapper::Is::PersistentStateMachine::State)
# will create FooStateTransition = Many-To-Many Unary relationship between FooState & FooState through transitions
@state_model.send(
:remix, n,
"DataMapper::Is::PersistentStateMachine::Transition",
:as => "destinations",
:for => Extlib::Inflection.demodulize(@state_model.name),
:via => "target"
)
# will create FooEvent
@event_model = model_from_context(DataMapper::Is::PersistentStateMachine::Event)
# add belongs to FooEvent association to transition model
@transition_model = Extlib::Inflection.constantize(self.name+"StateTransition")
@transition_model.send(:property, Extlib::Inflection.foreign_key(@event_model.to_s).to_sym, Integer)
@transition_model.send(:belongs_to, Extlib::Inflection.underscore(@event_model.to_s).to_sym)
# alias FooEvent association
@transition_model.send :define_method, 'event' do
send(Extlib::Inflection.underscore(@event_model.to_s))
end
self.send :define_method, 'hello_world' do
"hello world"
end
# alias
# DataMapper.logger.info "DDDDDD:"+
#transition_model.class_eval(<<-EOS, __FILE__, __LINE__ + 1)
# alias :event #{}
#EOS
end
module ClassMethods
# e.g. model_from_context(state_module)
def model_from_context(sub_module)
# use caller class name as a prefix
class_name = Extlib::Inflection.demodulize(self.name)+Extlib::Inflection.demodulize(sub_module.name)
DataMapper.logger.info "dynamic class name:"+class_name
klass = Class.new Object do
include DataMapper::Resource
end
#Give remixed model a name and create its constant
model = Object.full_const_set(class_name, klass)
# get instance methods, class methods & validators
model.send(:include,sub_module)
# model.send(:extend,sub_module)
# port the properties over...
sub_module.properties.each do |prop|
model.property(prop.name, prop.type, prop.options)
end
model
end
# def event_fk
# demodulized_name = Extlib::Inflection.demodulize(self.name)
# Extlib::Inflection.foreign_key(demodulized_name).to_sym
# end
end
module InstanceMethods
# just a convenience method
def state
#send(Extlib::Inflection.underscore(@state_model.to_s))
end
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment