1

I have a strange situation where the code:

c = Class.new { eval parser }

... works in IRB (ruby 1.9.3) but not in code. I've tried it with and without 'class Foo' wrapping my methods. This is frustrating, to say the least. I can copy the string parser's content directly into variable parser in irb, and then create the class using the above line and my methods are all there but when I do it in code, they aren't.

  • What is your error in you code ? – shingara Feb 15 '12 at 15:27
  • There is no error until I try to instantiate the new class. When I try to use my updated initialize (which passes it a DB handle) that fails. – Donald Scott Wilde Feb 15 '12 at 16:50
  • Maybe a more complete snippet of code can help – shingara Feb 15 '12 at 16:56
  • " def initialize( db ) @data = Hash.new @db = db @source = \"http://feeds.feedburner.com/FooFeed/\" end def already? end def nextcid end def save_ctables end def fetch end def savedata end " . /home/devel/recc_ruby_mysql/ruby/Content/FetcherBuilder.rb:154:in `initialize': wrong number of arguments(1 for 0) (ArgumentError) from /home/devel/recc_ruby_mysql/ruby/Content/FetcherBuilder.rb:154:in `new' – Donald Scott Wilde Feb 15 '12 at 17:36
  • The string in parser is (snipped) shown in the previous message although it doesn't come clean in the SO editor. `code` fetchclass = Class.new { eval parser } inst = fetchclass.new( @db ) puts inst.instance_variables.to_s `code` – Donald Scott Wilde Feb 15 '12 at 17:39
  • Please add that info to your question and delete the comments--it's illegible as comments. – Dave Newton Feb 15 '12 at 18:17
  • Sorry about that, @Dave. The parser _is_ a string. – Donald Scott Wilde Feb 15 '12 at 19:51

2 Answers2

2
C = Class.new
C.class_eval(code)

...Works for me in Ruby 1.9.2, even when saved in a file. Can you try and see if it works in 1.9.3?

Alex D
  • 29,755
  • 7
  • 80
  • 126
  • Same error. `code` fetchclass = Class.new fetchclass.class_eval( parser ) puts fetchclass.instance_methods.to_s ## doesn't show my methods inst = fetchclass.new( @db ) # crashes `code` Or, should I include the *entire* class def in the string including *class Foo*? – Donald Scott Wilde Feb 15 '12 at 19:07
  • I am dragging down 1.9.2p290 to install over 1.9.3, since the ruby-debuug19 also appears to choke on 1.9.3. :) – Donald Scott Wilde Feb 15 '12 at 19:41
  • 1.9.2p290 does not die with the initialize( @db ) but it still doesn't contain the methods and fails when I try to call fetch. ruby-debug19 doesn't work here either, so I can't dig in. – Donald Scott Wilde Feb 15 '12 at 20:00
  • I'm going to try using the exact code as you posted tomorrow. I'll edit my answer if I find a solution. – Alex D Feb 15 '12 at 20:53
  • I've learned that it isn't a matter of the initialize() method. It fails when I use standard initialize() and then a separate initialize_db( @db ) call. – Donald Scott Wilde Feb 15 '12 at 21:17
0

I've solved it.

The situation was that I was dynamically creating the definitions in order to make an optimized parser, and I was building it using incrementally added strings. As you can imagine, there was a lot of quote-escaping involved, especially with the MySQL queries. When I tested in irb, I forgot that using

puts parser

... evaluated the string while printing, removing one level of escaping while doing so.

The solution was simple: eval my string before class_eval'ing it.

fetchclass = Object.const_set(
                characteristics['shortname'],
                Class.new { class_eval( eval parser ) } )