alter-ego-activerecord 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/Manifest ADDED
@@ -0,0 +1,9 @@
1
+ Manifest
2
+ README.rdoc
3
+ Rakefile
4
+ alter-ego-activerecord.gemspec
5
+ lib/alter_ego/active_record_adapter.rb
6
+ test/adapter_test.rb
7
+ test/create_traffic_signals.rb
8
+ test/helper.rb
9
+ test/traffic_signal.rb
data/README.rdoc ADDED
@@ -0,0 +1,28 @@
1
+ = AlterEgo-ActiveRecord
2
+
3
+ == Motivation
4
+ AlterEgo is my favorite Ruby state machine for the following reasons:
5
+ 1. It's not dependent on ActiveRecord - it can be used on plain Ruby objects.
6
+ 2. It most closely follows the GOF State Pattern because it allows for
7
+ polymorphic behavior based on state.
8
+
9
+ Out of the box, AlterEgo doesn't play nicely with ActiveRecord because it
10
+ stores state in <tt>@state</tt>, whereas subclasses of ActiveRecord::Base
11
+ persist their <tt>attributes</tt> hash.
12
+
13
+ This mixin overrides the AlterEgo's accessor methods for state to allow it
14
+ to be properly persisted to a database, as well as serialized/unserialized as
15
+ json, yml, and xml.
16
+
17
+ == Installation
18
+ gem install alter-ego-activerecord
19
+
20
+ == Usage
21
+ Make sure the table your class maps to has a <tt>state</tt> column.
22
+
23
+ class Example < ActiveRecord::Base
24
+ include AlterEgo # include this first
25
+ include AlterEgo::ActiveRecordAdapter
26
+
27
+ # Your code here
28
+ end
data/Rakefile ADDED
@@ -0,0 +1,19 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'echoe'
4
+
5
+ Echoe.new('alter-ego-activerecord', '0.1.0') do |p|
6
+ p.description = "Adapter to allow ActiveRecord to persist and restore state of objects using the AlterEgo state machine"
7
+ p.author = "Paul Hieromnimon"
8
+ p.email = "paul.hieromnimon@gmail.com"
9
+ p.url = "http://github.com/pavlos/alter-ego-active-record"
10
+ p.runtime_dependencies = ["activerecord >=2.3.5", "alter-ego >=1.0.1" ]
11
+ p.ignore_pattern = ["*.sqlite"]
12
+ end
13
+
14
+ require 'rake/testtask'
15
+ Rake::TestTask.new(:test) do |test|
16
+ test.libs << 'lib' << 'test'
17
+ test.pattern = 'test/**/test_*.rb'
18
+ test.verbose = true
19
+ end
@@ -0,0 +1,37 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{alter-ego-activerecord}
5
+ s.version = "0.1.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Paul Hieromnimon"]
9
+ s.date = %q{2010-08-13}
10
+ s.description = %q{Adapter to allow ActiveRecord to persist and restore state of objects using the AlterEgo state machine}
11
+ s.email = %q{paul.hieromnimon@gmail.com}
12
+ s.extra_rdoc_files = ["README.rdoc", "lib/alter_ego/active_record_adapter.rb"]
13
+ s.files = ["Manifest", "README.rdoc", "Rakefile", "alter-ego-activerecord.gemspec", "lib/alter_ego/active_record_adapter.rb", "test/adapter_test.rb", "test/create_traffic_signals.rb", "test/helper.rb", "test/traffic_signal.rb"]
14
+ s.homepage = %q{http://github.com/pavlos/alter-ego-active-record}
15
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Alter-ego-activerecord", "--main", "README.rdoc"]
16
+ s.require_paths = ["lib"]
17
+ s.rubyforge_project = %q{alter-ego-activerecord}
18
+ s.rubygems_version = %q{1.3.7}
19
+ s.summary = %q{Adapter to allow ActiveRecord to persist and restore state of objects using the AlterEgo state machine}
20
+ s.test_files = ["test/adapter_test.rb"]
21
+
22
+ if s.respond_to? :specification_version then
23
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
24
+ s.specification_version = 3
25
+
26
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
27
+ s.add_runtime_dependency(%q<activerecord>, [">= 2.3.5"])
28
+ s.add_runtime_dependency(%q<alter-ego>, [">= 1.0.1"])
29
+ else
30
+ s.add_dependency(%q<activerecord>, [">= 2.3.5"])
31
+ s.add_dependency(%q<alter-ego>, [">= 1.0.1"])
32
+ end
33
+ else
34
+ s.add_dependency(%q<activerecord>, [">= 2.3.5"])
35
+ s.add_dependency(%q<alter-ego>, [">= 1.0.1"])
36
+ end
37
+ end
@@ -0,0 +1,30 @@
1
+ module AlterEgo
2
+ module ActiveRecordAdapter
3
+
4
+ def self.included klass
5
+ klass.after_initialize do |r|
6
+ r.state = r.state
7
+ end
8
+ end
9
+
10
+ # rails needs this method to be defined for the
11
+ # class method after_find to be able to take a block
12
+ # this is because of some performance optimization
13
+ def after_initialize; end
14
+
15
+ # Override methods from AlterEgo to store state
16
+ # in @attributes["state"] instead of @state
17
+ def state=(identifier)
18
+ # state needs to always be stored as a string - symbol serialization is strange
19
+ @attributes["state"] = identifier.to_s unless identifier.nil?
20
+ end
21
+
22
+ def state
23
+ result = ( @attributes["state"] || self.class.default_state)
24
+ result = result.to_sym unless result.nil?
25
+ assert(result.nil? || self.class.states.keys.include?(result))
26
+ result
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,77 @@
1
+ require 'helper'
2
+
3
+ class AdapterTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ CreateTrafficSignals.up
7
+ end
8
+
9
+ def test_state_stored_in_attributes
10
+ t = TrafficSignal.new
11
+ assert_not_nil t.attributes["state"]
12
+ t.state = :caution
13
+ assert_equal "caution", t.attributes["state"]
14
+ end
15
+
16
+ def test_state_stored_as_string
17
+ t = TrafficSignal.new
18
+ assert_equal String, t.attributes["state"].class
19
+ end
20
+
21
+ def test_state_returned_as_symbol
22
+ t = TrafficSignal.new
23
+ assert_equal Symbol, t.state.class
24
+ end
25
+
26
+ def test_state_is_persisted_and_restored
27
+ t = TrafficSignal.new
28
+ old_state = t.state
29
+ t.cycle!
30
+ new_state = t.state
31
+
32
+ #sanity check
33
+ assert_not_equal old_state, new_state
34
+
35
+ t.save!
36
+ t = t.reload
37
+
38
+ assert_equal t.state, new_state
39
+ end
40
+
41
+ def test_new_object_has_default_state
42
+ t=TrafficSignal.new
43
+ assert_equal t.state, TrafficSignal.default_state
44
+ assert_equal t.attributes["state"].to_sym, TrafficSignal.default_state
45
+ end
46
+
47
+ def test_yaml
48
+ require 'yaml'
49
+ t= TrafficSignal.new
50
+ t.cycle!
51
+ yaml = YAML::dump t
52
+ t2 = YAML::load yaml
53
+ assert_equal t.state, t2.state
54
+ end
55
+
56
+ def test_json
57
+ t = TrafficSignal.new
58
+ t.cycle!
59
+ json = t.to_json
60
+ t2 = TrafficSignal.new
61
+ t2.from_json json
62
+ assert_equal t.state, t2.state
63
+ end
64
+
65
+ def test_xml
66
+ t = TrafficSignal.new
67
+ t.cycle!
68
+ xml = t.to_xml
69
+ t2 = TrafficSignal.new
70
+ t2.from_xml xml
71
+ assert_equal t.state, t2.state
72
+ end
73
+
74
+ def teardown
75
+ CreateTrafficSignals.down
76
+ end
77
+ end
@@ -0,0 +1,19 @@
1
+ class CreateTrafficSignals < ActiveRecord::Migration
2
+
3
+ def self.up
4
+ create_table :traffic_signals do |t|
5
+ t.string :state
6
+ end
7
+ end
8
+
9
+ def self.down
10
+ drop_table :traffic_signals
11
+ end
12
+
13
+ # redirect output so running tests doesn't display a bunch of migration info
14
+ def self.puts *args
15
+ log = File.new "test/migrations.log", 'a+'
16
+ args.each {|a| log << a.to_s; log << "\n"}
17
+ log.close
18
+ end
19
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,10 @@
1
+ require 'test/unit'
2
+ require 'rubygems'
3
+ gem 'activerecord'
4
+ require 'active_record'
5
+ ActiveRecord::Base.establish_connection(:adapter=>'sqlite3', :database=>'test/testdb.sqlite')
6
+ gem 'alter-ego'
7
+ require 'alter_ego'
8
+ require 'alter_ego/active_record_adapter'
9
+ require 'create_traffic_signals'
10
+ require 'traffic_signal'
@@ -0,0 +1,27 @@
1
+ class TrafficSignal < ActiveRecord::Base
2
+ include AlterEgo
3
+ include AlterEgo::ActiveRecordAdapter
4
+
5
+
6
+ state :proceed, :default=>true do
7
+ handle :color do
8
+ "green"
9
+ end
10
+ transition :to => :caution, :on => :cycle!
11
+ end
12
+
13
+ state :caution do
14
+ handle :color do
15
+ "yellow"
16
+ end
17
+ transition :to => :stop, :on => :cycle!
18
+ end
19
+
20
+ state :stop do
21
+ handle :color do
22
+ "red"
23
+ end
24
+ transition :to => :proceed, :on => :cycle!
25
+ end
26
+
27
+ end
metadata ADDED
@@ -0,0 +1,113 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: alter-ego-activerecord
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Paul Hieromnimon
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-08-13 00:00:00 -07:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: activerecord
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 9
30
+ segments:
31
+ - 2
32
+ - 3
33
+ - 5
34
+ version: 2.3.5
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: alter-ego
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 21
46
+ segments:
47
+ - 1
48
+ - 0
49
+ - 1
50
+ version: 1.0.1
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ description: Adapter to allow ActiveRecord to persist and restore state of objects using the AlterEgo state machine
54
+ email: paul.hieromnimon@gmail.com
55
+ executables: []
56
+
57
+ extensions: []
58
+
59
+ extra_rdoc_files:
60
+ - README.rdoc
61
+ - lib/alter_ego/active_record_adapter.rb
62
+ files:
63
+ - Manifest
64
+ - README.rdoc
65
+ - Rakefile
66
+ - alter-ego-activerecord.gemspec
67
+ - lib/alter_ego/active_record_adapter.rb
68
+ - test/adapter_test.rb
69
+ - test/create_traffic_signals.rb
70
+ - test/helper.rb
71
+ - test/traffic_signal.rb
72
+ has_rdoc: true
73
+ homepage: http://github.com/pavlos/alter-ego-active-record
74
+ licenses: []
75
+
76
+ post_install_message:
77
+ rdoc_options:
78
+ - --line-numbers
79
+ - --inline-source
80
+ - --title
81
+ - Alter-ego-activerecord
82
+ - --main
83
+ - README.rdoc
84
+ require_paths:
85
+ - lib
86
+ required_ruby_version: !ruby/object:Gem::Requirement
87
+ none: false
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ hash: 3
92
+ segments:
93
+ - 0
94
+ version: "0"
95
+ required_rubygems_version: !ruby/object:Gem::Requirement
96
+ none: false
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ hash: 11
101
+ segments:
102
+ - 1
103
+ - 2
104
+ version: "1.2"
105
+ requirements: []
106
+
107
+ rubyforge_project: alter-ego-activerecord
108
+ rubygems_version: 1.3.7
109
+ signing_key:
110
+ specification_version: 3
111
+ summary: Adapter to allow ActiveRecord to persist and restore state of objects using the AlterEgo state machine
112
+ test_files:
113
+ - test/adapter_test.rb