On Sat, Apr 16, 2011 at 9:52 PM, Felipe Balbi <balbif / gmail.com> wrote:
> Hi all,
>
> To automate some of the tests I have to run, I decided to use ruby to
> generate some script files on a particular (very simple) language based
> on several possible input files. My first approach at this was to use
> inherited method on a parent class (which I called InputFormat) to hold
> all the children in an array. Then, different formats could become a
> child class of InputFormat and return a known data format (I decided to
> use an array of hashes because the output is really really simple) to
> the output generator code.
>
> So the idea is something like:
>
> class InputFormat
> =A0@children =3D []
>
> =A0def initialize(input)
> =A0 =A0@input =3D input
> =A0end
>
> =A0def parse
> =A0 =A0 / children.each { |child|
> =A0 =A0 =A0child.parse(@input) if child.supported?(@input)
> =A0 =A0}
> =A0end
>
> =A0def self.inherited(child)
> =A0 =A0@children << child
> =A0end
> end
>
> class AInputFormat < InputFormat
> =A0def supported?
> =A0 =A0# check if we can parse this type of file
> =A0end
>
> =A0def parse
> =A0 =A0# parse and generate array of hashes in known format
> =A0end
> end
>
>
> Then on the core file I would have something like:
>
> input =3D InputFormat.new(ARGV[0])
> input.parse
>
> As it turns out, this isn't working because AInputFormat will only
> inherit from InputFormat at the time I actually use it, am I right ? Any
> tips you guys could give me to achieve what I want ? (from several
> possible input formats generate one output format)

The above doesn't work, because the @children inside the instance
method "parse" is not the same as the @children inside the class
method "self.inherited". You have to give access to the class instance
variable, and then use that one from the parse method (the you will
see the next problem):

class InputFormat
  class << self
    attr_accessor :children
  end

  def initialize(input)
    @input =3D input
  end

  def parse
    self.class.children.each {|child| child.parse(@input) if
child.supported?(@input)}
  end

  def self.inherited(child)
    (@children ||=3D []) << child
  end
end

class AInputFormat < InputFormat
 def supported?
   # check if we can parse this type of file
 end

 def parse
   # parse and generate array of hashes in known format
 end
end

ruby-1.8.7-p334 :028 > input =3D InputFormat.new("test")
 =3D> #<InputFormat:0xb738bf50 @input=3D"test">
ruby-1.8.7-p334 :029 > input.parse
NoMethodError: undefined method `supported?' for AInputFormat:Class
	from (irb):11:in `parse'
	from (irb):11:in `each'
	from (irb):11:in `parse'
	from (irb):29

The next problem, as you see, is that you are defining instance
methods in the subclasses, but are calling them on the class. Maybe
the methods parse and supported? in the children could be class
methods, or maybe what you store in @children could be an instance of
the class.

Jesus.