Skip to content
Browse files

basically working

  • Loading branch information...
1 parent 7b6f2f0 commit 4a7f9b2dedc729e5ed739882eca9eadbb89bab61 michael committed Jan 4, 2010
Showing with 194 additions and 2 deletions.
  1. +2 −2 Rakefile
  2. +53 −0 dm-is-persistent_state_machine.gemspec
  3. +17 −0 lib/dm-is-persistent_state_machine.rb
  4. +122 −0 lib/is/persistent_state_machine.rb
View
4 Rakefile
@@ -5,8 +5,8 @@ begin
require 'jeweler'
Jeweler::Tasks.new do |gem|
gem.name = "dm-is-persistent_state_machine"
- gem.summary = %Q{TODO: one-line summary of your gem}
- gem.description = %Q{TODO: longer description of your gem}
+ gem.summary = %Q{A persistent State Machine for DataMapper}
+ gem.description = %Q{A persistent State Machine for DataMapper}
gem.email = "ma@zive.at"
gem.homepage = "http://github.com/michael/dm-is-persistent_state_machine"
gem.authors = ["michael"]
View
53 dm-is-persistent_state_machine.gemspec
@@ -0,0 +1,53 @@
+# Generated by jeweler
+# DO NOT EDIT THIS FILE DIRECTLY
+# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
+# -*- encoding: utf-8 -*-
+
+Gem::Specification.new do |s|
+ s.name = %q{dm-is-persistent_state_machine}
+ s.version = "0.0.1"
+
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
+ s.authors = ["michael"]
+ s.date = %q{2010-01-04}
+ s.description = %q{A persistent State Machine for DataMapper}
+ s.email = %q{ma@zive.at}
+ s.extra_rdoc_files = [
+ "LICENSE",
+ "README.rdoc"
+ ]
+ s.files = [
+ ".document",
+ ".gitignore",
+ "LICENSE",
+ "README.rdoc",
+ "Rakefile",
+ "VERSION",
+ "lib/dm-is-persistent_state_machine.rb",
+ "test/helper.rb",
+ "test/test_dm-is-persistent_state_machine.rb"
+ ]
+ s.homepage = %q{http://github.com/michael/dm-is-persistent_state_machine}
+ s.rdoc_options = ["--charset=UTF-8"]
+ s.require_paths = ["lib"]
+ s.rubygems_version = %q{1.3.5}
+ s.summary = %q{A persistent State Machine for DataMapper}
+ s.test_files = [
+ "test/helper.rb",
+ "test/test_dm-is-persistent_state_machine.rb"
+ ]
+
+ if s.respond_to? :specification_version then
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
+ s.specification_version = 3
+
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
+ s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
+ else
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
+ end
+ else
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
+ end
+end
+
View
17 lib/dm-is-persistent_state_machine.rb
@@ -0,0 +1,17 @@
+require 'rubygems'
+require 'forwardable'
+
+require 'dm-core'
+require 'dm-types'
+require 'dm-timestamps'
+require 'dm-validations'
+require 'dm-aggregates'
+
+
+# Temporary workaround until this is extracted into a gem
+$LOAD_PATH.unshift(File.expand_path('../../lib', __FILE__))
+
+require 'dm-is-persistent_state_machine/is/persistent_state_machine'
+
+# Activate the plugin
+DataMapper::Model.append_extensions DataMapper::Is::PersistentStateMachine
View
122 lib/is/persistent_state_machine.rb
@@ -0,0 +1,122 @@
+class StateTransition
+ include DataMapper::Resource
+
+ property :id, Serial
+
+ property :state_id, Integer, :required => true, :min => 1
+ property :target_id, Integer, :required => true, :min => 1
+ property :state_event_id, Integer, :required => true, :min => 1
+
+ belongs_to :state
+ belongs_to :target, 'State', :child_key => [:target_id]
+ belongs_to :state_event
+end
+
+class State
+ include DataMapper::Resource
+
+ property :id, Serial
+ property :code, String, :required => true, :unique => true, :unique_index => true
+ property :name, String, :required => true, :unique => true, :unique_index => true
+ property :editable, Boolean
+ property :sorter, Integer
+ property :type, Discriminator
+
+ # outgoing transitions
+ has n, :state_transitions, 'StateTransition', :child_key => [:state_id]
+
+ def events
+ evts = []
+ state_transitions.each do |transition|
+ # uses the generic event method
+ evts << transition.state_event
+ end
+ evts
+ end
+
+ # obj is the caller object
+ def trigger_event!(obj, event_code)
+ event = StateEvent.first(:code => event_code)
+ state_transitions.each do |transition|
+ if transition.state_event == event
+ obj.state = transition.target
+ obj.after_trigger_event(event)
+ return true
+ end
+ end
+ return false
+ end
+end
+
+class StateEvent
+ include DataMapper::Resource
+
+ property :id, Serial
+ property :code, String, :required => true, :unique => true, :unique_index => true
+ property :name, String, :required => true, :unique => true, :unique_index => true
+ property :type, Discriminator
+end
+
+
+module DataMapper
+ module Is
+ module PersistentStateMachine
+
+ class DmIsPersistentStateMachineException < Exception; end
+
+ ##
+ # fired when plugin gets included into Resource
+ #
+ def self.included(base)
+
+ end
+
+ ##
+ # Methods that should be included in DataMapper::Model.
+ # Normally this should just be your generator, so that the namespace
+ # does not get cluttered. ClassMethods and InstanceMethods gets added
+ # in the specific resources when you fire is :example
+ ##
+
+ def is_persistent_state_machine
+
+ # Add class-methods
+ extend DataMapper::Is::PersistentStateMachine::ClassMethods
+ extend Forwardable
+ # Add instance-methods
+ include DataMapper::Is::PersistentStateMachine::InstanceMethods
+
+ # target object must have a status associated
+ property :state_id, Integer, :required => true, :min => 1
+ belongs_to :state
+
+ DataMapper.logger.info "registering persistent state machine..."
+
+ # define delegators
+ def_delegators :@state, :events
+
+ # generate a FooState class that is derived from State
+ state_model = Object.full_const_set(self.to_s+"State", Class.new(State))
+ # generate a FooStateEvent class that is derived from StateEvent
+ event_model = Object.full_const_set(self.to_s+"StateEvent", Class.new(StateEvent))
+ end
+
+ ##
+ # fired after trigger_event! is called on resource
+ #
+ def after_trigger_event(event)
+ end
+
+ module ClassMethods
+
+ end # ClassMethods
+
+ module InstanceMethods
+ def trigger_event!(event_code)
+ # delegate to State#trigger!
+ self.state.trigger_event!(self, event_code)
+ end
+ end # InstanceMethods
+ end # PersistentStateMachine
+ end # Is
+end # DataMapper

0 comments on commit 4a7f9b2

Please sign in to comment.
Something went wrong with that request. Please try again.