From: Marc-antoine Kruzik Date: 2009-09-07T17:10:07+09:00 Subject: Re: something.new( :attribute => value) thing Martin Boese wrote: > On Sun, 2009-09-06 at 03:06 +0900, Marc-antoine Kruzik wrote: >> > A.send(:attr_accessor, key) >> > send("#{key}=", val) >> >> This solution is what I was looking for. >> With a bit of work, I will be able to write code like this : > > Hi Marc, > > I'd try to keep it simple: > > class A > def initialize(param_a, param_b, options = {}) > @x = options[:x] || 50 # defaults to 50 if not specified > @y = options[:y] || 100 > @z = options[:z] || 'red' > puts "Initialized with #{@x}/#{@y}/#{@z}" > end > end Use default values is a goog idea. The problem is, you have to write the code for @x, @y and @z. My version is now this one : I have three classes : GUI_Object > GUI_Object_Graphic > Picture The purpose of the code is to avoid to write a lot of code when you are working on classes like Picture. (I know, I don't optimize my code, if you have better solution, it would be nice.) class GUI_Object attr_accessor :parent @accessors = [:parent] def initialize(parent=nil, hash=nil) @parent = parent hash = param_hash_1(parent, hash) modify_accessor(hash) end def param_hash_1(parent, hash) if hash.is_a?(Hash) return hash elsif parent.is_a?(Hash) @parent = nil return parent end return nil end def modify_accessor(hash) return if hash == nil hash.each do |key, val| if self.class.check_accessor(key) == true # Here's the 7stud function : send("#{key}=", val) else raise("unknown accessor for class #{self.class}: #{key}") end end end def self.check_accessor(acc) if self.accessor != nil and self.accessor.include?(acc) return true else if self != GUI_Object return true if self.ancestors[1].check_accessor(acc) == true end end return false end def self.accessor return @accessors end end class GUI_Object_Graphic < GUI_Object attr_reader :x attr_reader :y attr_accessor :width attr_accessor :height @accessors = [:x, :y, :width, :height] def initialize(parent=nil, x=0, y=0, width=0, height=0, hash=nil) @x = x @y = y @width = width @height = height hash = param_hash(x, y, width, height, hash) @x = 0 if @x == nil @y = 0 if @y == nil @width = 0 if @width == nil @height = 0 if @height == nil super(parent, hash) end def param_hash(x, y, width, height, hash) if hash.is_a?(Hash) return hash elsif x.is_a?(Hash) @x = 0 return x elsif y.is_a?(Hash) @y = 0 return y elsif width.is_a?(Hash) @width = 0 return width elsif height.is_a?(Hash) @height = 0 return height end return nil end end class Picture < GUI_Object_Graphic attr_accessor :bg_color attr_accessor :cadre attr_accessor :marges attr_accessor :image attr_accessor :zoom # I ONLY have to create THIS list to use the attributes I want @accessors = [:bg_color, :picture, :zoom] # So, it's really, really not difficult def initialize(parent=nil, x=0, y=0, width=0, height=0, hash=nil) # Default values @bg_color = nil @zoom = 1 super @marges = [0, 0, 0, 0] @cadre = nil end end So I can use these codes to create a Picture : x = y = width = height = 0 a = Picture.new(nil, x, y, width, height) a = Picture.new(nil, x, y, :zoom => 2, :width => 30, :bg_color => "red") I'm not using a class variable like @@accessors, because of the problems with class variables. With this code, people can easily create new classes like Picture. And with a simple list like @accessors = [:bg_color, :picture, :zoom], they can allow to use only the attributes they want. It's part of my code to create a super-easy-to-use GUI working with a video game graphical library. Here's a screenshot : http://i291.photobucket.com/albums/ll318/KingKadelfek/screen05-f95306.png I want the users able to create new components (such as Picture), so I try to find the most easiest way. -- Posted via http://www.ruby-forum.com/.