8da0e26ce3ceb5909e60973ad1b520c7

This is a trivial example of what I'm wanting to do. My focus is with the definition of ObjectContainer. Currently the method add_object uses an anonymous Module to extend an instance with the a method that returns that object passed in.

I feel like there should be a better way to accomplish this, but am fairly new to ruby especially when it comes to things of this nature.

#the object to be added to ObjectContainer
# :label is used to defined accessor method name
# :value is used for return value of to_s
class MyObject < Struct.new(:label, :value)
  def to_s
    self.value
  end
end

#container class to hold instances of MyObject
class ObjectContainer
  def add_object(q)
    mod = Module.new do
      define_method q.label do; q; end
    end
    extend mod
  end

  class_eval{ alias :<< add_object }
end

container = ObjectContainer.new

#add 5 objects to container
(1..5).each {|n|
  obj = MyObject.new
  obj.label = "label#{n}"  #accessor name will be label1, label2, etc
  obj.value = "value #{n}"
  container << obj
}

#example usage of objects
container.instance_eval {
  (1..5).each {|n|
    o = send("label#{n}")
    puts "obj #{n}: #{o.label} = #{o}"
  }
}

Refactorings

No refactoring yet !

A8d3f35baafdaea851914b17dae9e1fc

Adam

October 7, 2009, October 07, 2009 20:10, permalink

No rating. Login to rate!
class ObjectContainer < Hash
  def <<(object)
    self[object.label] = object
  end
  
  def method_missing(method, *args, &block)
    if method.to_s =~ /(.*)=/
      self[$1] = args.first
    else
      self[method.to_s] || super
    end
  end
end
(1..5).each do |n|
  o = container.send("label#{n}")
  puts "obj #{n}: #{o.label} = #{o}"
end
D41d8cd98f00b204e9800998ecf8427e

mainej

October 8, 2009, October 08, 2009 04:03, permalink

No rating. Login to rate!

I think Adam is implying that you don't need any fancy define_method/instance_eval programming to get the functionality you seem to want: add an object to a container, then retrieve it later with its label. Maybe iterate through all the objects in the container, too. That sounds very much like a hash, so ... inherit from Hash.

class ObjectContainer < Hash
  def <<(object)
    self[object.label] = object
  end
end

class MyObject < Struct.new(:label, :value)
  def to_s
    self.value
  end
end

container = ObjectContainer.new

#add 5 objects to container
(1..5).each {|n|
  obj = MyObject.new
  obj.label = "label#{n}"
  obj.value = "value #{n}"
  container << obj
}

o = container["label3"]
puts "obj #{o}"

#even more interesting:
container.each do |label, object|
  puts "label: #{label} obj: #{object}"
end

#and other good stuff you get from hashes
puts container.sort_by { |label, object| label }.inspect
D85d44a0eca045f40e5a31449277c26c

Ben Marini

October 8, 2009, October 08, 2009 06:53, permalink

No rating. Login to rate!

Seems to me like you might as well just use the built-in Hash.

# Method 1 (Using ObjectContainer)
obj = MyObject.new("label", "value")
container = ObjectContainer.new
container << obj
puts "#{container.label}"

# Method 2 (using built-in Hash class)
container = {}
container[:label] = "value"
puts "#{container[:label]}"
D85d44a0eca045f40e5a31449277c26c

Ben Marini

October 8, 2009, October 08, 2009 06:57, permalink

No rating. Login to rate!

Is the only point of ObjectContainer to provide a different syntax for accessing it's elements? You could also use a Hash with your "MyObject".

c = {}
c[:label1] = MyObject.new("label1", "value1")
8da0e26ce3ceb5909e60973ad1b520c7

loomis53.myopenid.com

October 9, 2009, October 09, 2009 18:05, permalink

No rating. Login to rate!

Actually I'm toying with the idea of implementing a simple DSL. But my purpose here is more for learning than anything else.

Initially I thought using define_method was a cleaner approach than method_missing, with define_method having less chance for unintended side effects. But method_missing is much simpler (of course as stated I could just as well use a hash).

Out of curiosity, I ran some benchmarks and my define_method approach seems to be about 10 times slower than method_missing, which is something else to keep in mind.

Thanks for the feedback, everyone.

D85d44a0eca045f40e5a31449277c26c

Ben Marini

October 11, 2009, October 11, 2009 20:50, permalink

No rating. Login to rate!

Jim Weirich's builder gem for xml is a really good example of a DSL that uses method_missing.

2f605592095a0cbca418332b5ab2aa41

Pharmg156

November 1, 2009, November 01, 2009 18:49, permalink

No rating. Login to rate!

Very nice site! cheap cialis http://apeoixy.com/xqqava/4.html

Very nice site! cheap cialis http://apeoixy.com/xqqava/4.html
225f72b5dae873b47ff0336fb9c560f3

yTRQYb

December 22, 2009, December 22, 2009 08:04, permalink

No rating. Login to rate!

Hi! kGYgfb

Hi! kGYgfb
9ce984530513a57b60a710cc370cf631

nZqvlvCA

December 22, 2009, December 22, 2009 11:05, permalink

No rating. Login to rate!

Hi! iQcZJVj

Hi! iQcZJVj
874453a275b5238803f0dfb41e66c10d

WSBypM

April 16, 2010, April 16, 2010 03:17, permalink

No rating. Login to rate!

UWxQImvM

UWxQImvM

Your refactoring





Format Copy from initial code

or Cancel