M
Michael 'entropie' Trommer
--E39vaYmALEf/7YXx
Content-Type: multipart/mixed; boundary="OXfL5xGRrasGEqWY"
Content-Disposition: inline
--OXfL5xGRrasGEqWY
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Hello,
I found this State-pattern example on [1], and was interested to
find a way to make this more useable for standard classes (not just
servers as in the example)
I'am not so skilled in OO coding and ruby, so iam interested what you all think.
(and is it another implementation of the state pattern or iam on the
wrong path?)
[1] http://www.rubygarden.org/ruby?StatePattern
So long
--
Michael 'entropie' Trommer; http://ackro.org
ruby -e "0.upto((a='njduspAhnbjm/dpn').size-1){|x| a[x]-=1}; p 'mailto:'+a"
--OXfL5xGRrasGEqWY
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="state_pattern.rb"
Content-Transfer-Encoding: quoted-printable
# =3D Example
# class StateTest
#
# include StateHelper
#
# def denied_during_curr_state_msg(meth, state)
# "my method saz now: calling `#{meth}` during `#{state}` not allowed"
# end
#=09
# def initialize
# @state =3D StateHelper::StateOff
# end
#
# def on_msg(msg)
# true
# end
#
# def off_bar
# true
# end
#
# def meth
# puts "sup?"
# end
# end
#
# a =3D StateTest.new # nothing cool happend
# a.msg "foo" # is not allowed, because msg has the prefix `on`, rai=
se NotAllowedDuringState
# a.connect # toggles state, comes from module StateHelper
# a.msg "bar" # is now allowed, raise NotAllowedDuringState error
# a.connect # not allowed, because we are already "connected", rai=
se NotAllowedDuringState
# a.disconnect # allowed, comes as +connect* from StateHelper module
# a.meth # returns "sup?"
# a.foo # raise a NoMethodError
module StateHelper
# def[ine] this method with argument <tt>meth</tt> and <tt>state</tt> for
# yourself if you want
DefaultErrDef =3D 'denied_during_curr_state_msg'
class NotAllowedDuringState < Exception; end
class StateOn < TrueClass; end
class StateOff < FalseClass; end=09
def state?; @state; end
=09
# toggles @state
def toggle_state
@state =3D (state? =3D=3D StateOn) ? StateOff : StateOn
puts "state is now #{@state}"
end
# returns both state methods as array
# first one is method for actual state, second only for debugging
def mkMethodString(meth, state)
arr =3D "off_#{meth}", "on_#{meth}"
if @state.superclass =3D=3D TrueClass
return arr.reverse
end
arr
end
=09
# grep virtual method call and check allowed during @state
def method_missing(meth, *par)
n, f =3D mkMethodString(meth, @state)
if self.methods.include?(n)
self.send(n, *par)
elsif self.methods.include?(f)
raise NotAllowedDuringState, denied_during_curr_state_msg(meth, @state)
else
# raise original expetion
raise NoMethodError, "undefined method `#{meth}' #{self.inspect}"
end
end
# toggles state
alias ff_connect :toggle_state
# toggles state
alias n_disconnect :toggle_state
# ovewrite it if you need to
def initialize
@state =3D StateHelper::StateOff
end
end
class StateTest
include StateHelper
# used to overwrite error msg... i dunno..
def denied_during_curr_state_msg(meth, state)
"my error msg is cooler and saz: calling `#{meth}` during `#{state}` not =
allowed"
end
=09
def on_msg(msg)
true
end
def off_bar
true
end
def meth
puts "sup?"
end
end
a=3DStateTest.new
a.msg "foo" # is not allowed, because msg has the prefix `on`
a.connect # toggles state, comes from module StateHelper
a.msg "bar" # is now allowed
a.connect # not allowed, because we are already "connected"
a.disconnect # allowed
a.meth # returns "sup?"
a.foo
--OXfL5xGRrasGEqWY--
--E39vaYmALEf/7YXx
Content-Type: application/pgp-signature
Content-Disposition: inline
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)
iD8DBQFDvxKOBBd8ye5RguQRAiE/AJ9mqEc1GoZDWkHvwfz61Hul1FgPpQCgwh/q
YqK/fEvjaVim8sO8MIAjEcc=
=BTFJ
-----END PGP SIGNATURE-----
--E39vaYmALEf/7YXx--
Content-Type: multipart/mixed; boundary="OXfL5xGRrasGEqWY"
Content-Disposition: inline
--OXfL5xGRrasGEqWY
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Hello,
I found this State-pattern example on [1], and was interested to
find a way to make this more useable for standard classes (not just
servers as in the example)
I'am not so skilled in OO coding and ruby, so iam interested what you all think.
(and is it another implementation of the state pattern or iam on the
wrong path?)
[1] http://www.rubygarden.org/ruby?StatePattern
So long
--
Michael 'entropie' Trommer; http://ackro.org
ruby -e "0.upto((a='njduspAhnbjm/dpn').size-1){|x| a[x]-=1}; p 'mailto:'+a"
--OXfL5xGRrasGEqWY
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="state_pattern.rb"
Content-Transfer-Encoding: quoted-printable
# =3D Example
# class StateTest
#
# include StateHelper
#
# def denied_during_curr_state_msg(meth, state)
# "my method saz now: calling `#{meth}` during `#{state}` not allowed"
# end
#=09
# def initialize
# @state =3D StateHelper::StateOff
# end
#
# def on_msg(msg)
# true
# end
#
# def off_bar
# true
# end
#
# def meth
# puts "sup?"
# end
# end
#
# a =3D StateTest.new # nothing cool happend
# a.msg "foo" # is not allowed, because msg has the prefix `on`, rai=
se NotAllowedDuringState
# a.connect # toggles state, comes from module StateHelper
# a.msg "bar" # is now allowed, raise NotAllowedDuringState error
# a.connect # not allowed, because we are already "connected", rai=
se NotAllowedDuringState
# a.disconnect # allowed, comes as +connect* from StateHelper module
# a.meth # returns "sup?"
# a.foo # raise a NoMethodError
module StateHelper
# def[ine] this method with argument <tt>meth</tt> and <tt>state</tt> for
# yourself if you want
DefaultErrDef =3D 'denied_during_curr_state_msg'
class NotAllowedDuringState < Exception; end
class StateOn < TrueClass; end
class StateOff < FalseClass; end=09
def state?; @state; end
=09
# toggles @state
def toggle_state
@state =3D (state? =3D=3D StateOn) ? StateOff : StateOn
puts "state is now #{@state}"
end
# returns both state methods as array
# first one is method for actual state, second only for debugging
def mkMethodString(meth, state)
arr =3D "off_#{meth}", "on_#{meth}"
if @state.superclass =3D=3D TrueClass
return arr.reverse
end
arr
end
=09
# grep virtual method call and check allowed during @state
def method_missing(meth, *par)
n, f =3D mkMethodString(meth, @state)
if self.methods.include?(n)
self.send(n, *par)
elsif self.methods.include?(f)
raise NotAllowedDuringState, denied_during_curr_state_msg(meth, @state)
else
# raise original expetion
raise NoMethodError, "undefined method `#{meth}' #{self.inspect}"
end
end
# toggles state
alias ff_connect :toggle_state
# toggles state
alias n_disconnect :toggle_state
# ovewrite it if you need to
def initialize
@state =3D StateHelper::StateOff
end
end
class StateTest
include StateHelper
# used to overwrite error msg... i dunno..
def denied_during_curr_state_msg(meth, state)
"my error msg is cooler and saz: calling `#{meth}` during `#{state}` not =
allowed"
end
=09
def on_msg(msg)
true
end
def off_bar
true
end
def meth
puts "sup?"
end
end
a=3DStateTest.new
a.msg "foo" # is not allowed, because msg has the prefix `on`
a.connect # toggles state, comes from module StateHelper
a.msg "bar" # is now allowed
a.connect # not allowed, because we are already "connected"
a.disconnect # allowed
a.meth # returns "sup?"
a.foo
--OXfL5xGRrasGEqWY--
--E39vaYmALEf/7YXx
Content-Type: application/pgp-signature
Content-Disposition: inline
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)
iD8DBQFDvxKOBBd8ye5RguQRAiE/AJ9mqEc1GoZDWkHvwfz61Hul1FgPpQCgwh/q
YqK/fEvjaVim8sO8MIAjEcc=
=BTFJ
-----END PGP SIGNATURE-----
--E39vaYmALEf/7YXx--