From: "Ara.T.Howard" Date: 2004-01-14T16:11:39+09:00 Subject: Re: What object-configuration approach to use? On Wed, 14 Jan 2004, Mike Williams wrote: > Date: Wed, 14 Jan 2004 13:04:24 +0900 > From: Mike Williams > Newsgroups: comp.lang.ruby > Subject: What object-configuration approach to use? > > Consider a class that supports a number of configurable properties. > ---- > 3. OptionalArgumentMap > > Another alternative is pass in a map of named optional args, e.g. > > class Link > def initialize(url, content, args = {}) > @url = url > @content = content > @title = args[:title] > @target = args[:target] > end > end > > link = Link.new("http://", "here", {:title => "the whole story"}) > helplink = Link.new("/help", "help" {:target => "helpFrame"}) > > As I understand it, there's some syntax-sugar planned for Ruby-2.0, that > would make this a bit cleaner: > > link = Link.new("http://", "here", title: "the whole story") > > Right? i use variations of this alot: ~/eg/ruby > cat foo.rb module M def hashify(*args); args.inject({}){|h,a| h.update a}; end end class C include M attr :opts attr :foo, true attr :bar, true def initialize(*args) @opts = hashify(*args) @opts.map{|k,v| send "#{ k }=".intern, v} end end c = C.new :foo => 42, :bar => 42.0 d = C.new c.opts, 'bar' => 'over-ridden' p c.foo p c.bar p d.foo p d.bar ~/eg/ruby > ruby foo.rb 42 42.0 42 "over-ridden" it's great way to get up and running quickly and not need to change function prototypes (read 'interface') so often. as the need arises for type/range checking, etc. i just do def foo= value raise unless Array = value @foo = value end etc. i've found this to be very useful for at least a couple of reaons: * keeps prototypes short * keeps interface consistent - it never changes ;-) * allows 'argumement inheritence' (see above) * makes it _easy_ to pass in options from command line to objects or yaml configs * reads nice IMHO - i never forget what each parm is since it's named Connection.new :port => 80, :type => 'udp' vs Connection.new 80, 'udp' * allows one to quite easily pass a new parameter to a deeply nested method without changes 40 prototypes on the way down about the only thing i can say is that i makes it quite important to doccument your methods so it is known what parameters a method expects. on the other hand it easy enough to make methods throw a 'usage' exception with details of calling semantics. -a -- ATTN: please update your address books with address below! =============================================================================== | EMAIL :: Ara [dot] T [dot] Howard [at] noaa [dot] gov | PHONE :: 303.497.6469 | ADDRESS :: E/GC2 325 Broadway, Boulder, CO 80305-3328 | STP :: http://www.ngdc.noaa.gov/stp/ | NGDC :: http://www.ngdc.noaa.gov/ | NESDIS :: http://www.nesdis.noaa.gov/ | NOAA :: http://www.noaa.gov/ | US DOC :: http://www.commerce.gov/ | | The difference between art and science is that science is what we | understand well enough to explain to a computer. | Art is everything else. | -- Donald Knuth, "Discover" | | /bin/sh -c 'for l in ruby perl;do $l -e "print \"\x3a\x2d\x29\x0a\"";done' ===============================================================================