method_missing question

J

Joe Van Dyk

Can someone complete the psuedo-code in SomeObject#method_missing for
me? Or suggest a better way of doing this? The attributes for
SomeObject are, in my application, are generated from a configuration
file.

Thanks
Joe

class SomeObject
def initialize
@attributes = { :x_pos => 20, :y_pos => 30, :z_pos => 40 }
end

def method_missing(method, *args)
# test to see if this is a get or set method
if method contains an =
set(method minus the equal, args)
else
get(method)
end
end

def get(attribute)
@attributes[attribute]
end

def set(attribute, value)
@attributes[attribute] = value
end
end

my_obj = SomeObject.new
my_obj.x_pos = 20
my_obj.z_pos = 40

assert(20, my_obj.x_pos)
assert(40, my_obj.z_pos)
 
R

Ryan Davis

Can someone complete the psuedo-code in SomeObject#method_missing for
me? Or suggest a better way of doing this? The attributes for
SomeObject are, in my application, are generated from a configuration
file.

class SomeObject
def initialize
@attributes = { :x_pos => 20, :y_pos => 30, :z_pos => 40 }
end

def method_missing(meth, *args) # notice rename - don't like having
vars the same as methods
# test to see if this is a get or set method
if meth =~ /^(.+)=$/
set($1.intern, args)
else
get(meth)
end
end

def get(attribute)
@attributes[attribute]
end

def set(attribute, value)
# you might also want to check at this stage that the attribute
exists
@attributes[attribute] = value
end
end

my_obj = SomeObject.new
my_obj.x_pos = 20
my_obj.z_pos = 40

assert(20, my_obj.x_pos)
assert(40, my_obj.z_pos)
 
J

Joe Van Dyk

Can someone complete the psuedo-code in SomeObject#method_missing for
me? Or suggest a better way of doing this? The attributes for
SomeObject are, in my application, are generated from a configuration
file.

Thanks
Joe

class SomeObject
def initialize
@attributes = { :x_pos => 20, :y_pos => 30, :z_pos => 40 }
end

def method_missing(method, *args)
# test to see if this is a get or set method
if method contains an =
set(method minus the equal, args)
else
get(method)
end
end

Here's what I have so far. This works, but wondering if something
better's out there.

def method_missing(method, *args)
puts "method missing called with #{method} and #{args}"

if method.to_s =~ /^(.+)=$/
set($1.to_sym, *args)
else
get(method.to_sym)
end
end
def get(attribute)
@attributes[attribute]
end

def set(attribute, value)
@attributes[attribute] = value
end
end

my_obj = SomeObject.new
my_obj.x_pos = 20
my_obj.z_pos = 40

assert(20, my_obj.x_pos)
assert(40, my_obj.z_pos)
 
R

Ryan Davis

Here's what I have so far. This works, but wondering if something
better's out there.

def method_missing(method, *args)
puts "method missing called with #{method} and #{args}"

if method.to_s =~ /^(.+)=$/
set($1.to_sym, *args)
else
get(method.to_sym)
end
end

That looks fine to me. I, by habit/musclememory, use intern instead of
to_sym. You shouldn't need to do it for your get as method_missing
should be passed a symbol in the first place.
 
J

Joe Van Dyk

That looks fine to me. I, by habit/musclememory, use intern instead of
to_sym. You shouldn't need to do it for your get as method_missing
should be passed a symbol in the first place.


Thanks for the input. My previous function failed on code like

assert(my_obj.x_pos == 10)

so I needed to add an

elsif method.to_s =~ /^(.+)==$/
get($1.to_sym)

to SomeObject#method_missing.
 
R

Robert Klemme

Joe Van Dyk said:
Can someone complete the psuedo-code in SomeObject#method_missing for
me? Or suggest a better way of doing this? The attributes for
SomeObject are, in my application, are generated from a configuration
file.

Thanks
Joe

class SomeObject
def initialize
@attributes = { :x_pos => 20, :y_pos => 30, :z_pos => 40 }
end

def method_missing(method, *args)
# test to see if this is a get or set method
if method contains an =
set(method minus the equal, args)
else
get(method)
end
end

def get(attribute)
@attributes[attribute]
end

def set(attribute, value)
@attributes[attribute] = value
end
end

my_obj = SomeObject.new
my_obj.x_pos = 20
my_obj.z_pos = 40

assert(20, my_obj.x_pos)
assert(40, my_obj.z_pos)

Did you consider using OpenStruct?

require 'ostruct'

my_obj = OpenStruct.new
my_obj.x_pos = 20
my_obj.z_pos = 40

assert(20, my_obj.x_pos)
assert(40, my_obj.z_pos)

Kind regards

robert
 
F

Florian Gross

Joe said:
Can someone complete the psuedo-code in SomeObject#method_missing for
me? Or suggest a better way of doing this? The attributes for
SomeObject are, in my application, are generated from a configuration
file.

Thanks
Joe

class SomeObject
def initialize
@attributes = { :x_pos => 20, :y_pos => 30, :z_pos => 40 }
end

Perhaps you could do it simpler by changing this logic? I was thinking
along the lines of

def initialize()
{ :x_pos => 20, :y_pos => 30, :z_pos => 40 }.each do |key, value|
instance_variable_set("@#{key}", value)
class << self; self; end.send:)attr_accessor, key)
end
end

But that won't quite work when the field set can change after initialize
has been called. When you know all the keys upfront you can also move
the accessors to the class definition.
 

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,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top