something.new( :attribute => value) thing

  • Thread starter Marc-antoine Kruzik
  • Start date
M

Marc-antoine Kruzik

Hello, I saw something very interesting in the code of FXRuby, and I
would like to use this kind of code in my scripts :

My_Window.new(app, "Button Test", :eek:pts => DECOR_ALL, :x => 100, :y =>
100)


I'm only able to do "classic" initialisations, such as :
My_Window.new(app, "Button Test", DECOR_ALL, 100, 100)



What is the easiest way to create class which use the ":eek:pts => ... x =>
... y => " part ?
I'm sorry, I don't know the name of this feature, so it's quite
difficult to find informations about it.


I wrote a code to use for sample.


class My_Window

attr_accessor :application
attr_accessor :title

# Do I have to create attributes ?
attr_accessor :eek:pts
attr_accessor :x
attr_accessor :y

def initialize(application, title, ??? )

@application = application
@title = title

???

end


end


Thanks !
 
T

Tim Hunter

Marc-antoine Kruzik said:
Hello, I saw something very interesting in the code of FXRuby, and I
would like to use this kind of code in my scripts :

My_Window.new(app, "Button Test", :eek:pts => DECOR_ALL, :x => 100, :y =>
100)


I'm only able to do "classic" initialisations, such as :
My_Window.new(app, "Button Test", DECOR_ALL, 100, 100)



What is the easiest way to create class which use the ":eek:pts => ... x =>
... y => " part ?
I'm sorry, I don't know the name of this feature, so it's quite
difficult to find informations about it.

When the trailing method arguments are key => value pairs, Ruby collects
them into a hash and passes the hash as the last argument to the method.
Frequently the keys are symbols such as :eek:pts or :x. The keys don't have
to be symbols, though.

See http://www.softiesonrails.com/2007/8/27/ruby-101-hashes-are-cool
 
J

Jesús Gabriel y Galán

Hello, I saw something very interesting in the code of FXRuby, and I
would like to use this kind of code in my scripts :

My_Window.new(app, "Button Test", :eek:pts => DECOR_ALL, :x => 100, :y =>
100)
What is the easiest way to create class which use the ":eek:pts => ... x =>
... y => " part ?
I'm sorry, I don't know the name of this feature, so it's quite
difficult to find informations about it.

As Tim said, Ruby collects key-value pairs at the end of the argument
list as a Hash. Here's an example:

irb(main):007:0> def test(a,b,c)
irb(main):008:1> p [a,b,c]
irb(main):009:1> p c.class
irb(main):010:1> c.each {|key,value| p [key,value]}
irb(main):011:1> end
=> nil
irb(main):012:0> test(1,2,:xxx => 5, :y => 55)
[1, 2, {:xxx=>5, :y=>55}]
Hash
[:xxx, 5]
[:y, 55]

Jesus.
 
7

7stud --

Marc-antoine Kruzik said:
# Do I have to create attributes ?
attr_accessor :eek:pts
attr_accessor :x
attr_accessor :y

def initialize(application, title, ??? )

@application = application
@title = title

???

end


end


class A

def initialize(arg1, arg2, hash)
hash.each do |key, val|
A.send:)attr_accessor, key)
send("#{key}=", val)
end
end

end


a = A.new("hello", "world", :x => 10, :y => 20, :z => "red")
puts a.x
puts a.y
puts a.z

--output:--
10
20
red

a.x = "hello"
a.y = "goodbye"
a.z = "the end"

puts a.x
puts a.y
puts a.z

--output:--
hello
goodbye
the end
 
M

Marc-antoine Kruzik

Tim said:
When the trailing method arguments are key => value pairs, Ruby collects
them into a hash and passes the hash as the last argument to the method.
Frequently the keys are symbols such as :eek:pts or :x. The keys don't have
to be symbols, though.

See http://www.softiesonrails.com/2007/8/27/ruby-101-hashes-are-cool

I know the hashes, but I didn't know what was the best way to use
arguments this way (my first post). Nice link.

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 :

a = A.new("hello", "world", :x => 10, :y => 20, :z => "red")
a = A.new("hello", "world", :z => "red", :y => 20, :x => 10)
a = A.new("hello", "world", :z => "red")
a = A.new("hello", "world", :x => 10)

Thank you very much, 7stud.
 
M

Martin Boese

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

a = A.new("hello", "world", :x => 10, :y => 20, :z => "red")
Initialized with 10/20/red

a = A.new("hello", "world", :z => "red", :y => 20, :x => 10)
Initialized with 10/20/red

a = A.new("hello", "world", :z => "red")
Initialized with 50/100/red

a = A.new("hello", "world", :x => 10)
Initialized with 10/100/red



- Martin
 
M

Marc-antoine Kruzik

Martin said:
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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,185
Members
46,736
Latest member
AdolphBig6

Latest Threads

Top