--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 :off_connect :toggle_state
	# toggles state
	alias :on_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--

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"
# =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 :off_connect :toggle_state
	# toggles state
	alias :on_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


-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)

iD8DBQFDvxKOBBd8ye5RguQRAiE/AJ9mqEc1GoZDWkHvwfz61Hul1FgPpQCgwh/q
YqK/fEvjaVim8sO8MIAjEcc=
=BTFJ
-----END PGP SIGNATURE-----