Class exists, but resolves to nil in some contexts

All,

I can't explain this behaviour, and I'm reasonably sure it's not a bug and
it's something subtle that I've missed.

I'm on Ruby 2.2.0p0. I have a class called 'App::TrainStatus', which has
an initialize method defined which prints a single-line string for
debugging. I have a second class, 'App::TrainFactory', which takes an XML
message and, depending on the content of the XML, returns one of a number
of classes.

The problem I have is that App::TrainStatus.new returns nil from within
TrainFactory:

  def self.parse_message(msg)
    return App::TrainStatus.new
  end

If I change App::TrainStatus to another class which I haven't defined, e.g.
App::Foobar, I get an appropriate error.

If I insert the following line in to the code:

  puts App::TrainStatus

...then I get App::TrainStatus returned. If I put ".class" at the end, I
get "Class" returned - so it seems as though the class is loaded and
available.

What's puzzling me is that the TrainStatus class is loaded and available,
but a call to 'new' doesn't do anything - it doesn't even print the debug
message in the initialize() method of the class.

Can anyone give me some hints on troubleshooting?

Peter

All,

A case of http://www.sjbaker.org/humor/cardboard_dog.html - I downgraded to
Ruby 2.1.5p273 and exactly the same code works, so I suspect a bug in
2.2.0p0.

I can continue on 2.1.5p273 as there's nothing in 2.2.0p0 I absolutely need
- just putting this out there for anyone who might have a similar problem.

Peter

···

On 16 March 2015 at 22:05, Peter Hicks <peter.hicks@poggs.co.uk> wrote:

All,

I can't explain this behaviour, and I'm reasonably sure it's not a bug and
it's something subtle that I've missed.

I'm on Ruby 2.2.0p0. I have a class called 'App::TrainStatus', which has
an initialize method defined which prints a single-line string for
debugging. I have a second class, 'App::TrainFactory', which takes an XML
message and, depending on the content of the XML, returns one of a number
of classes.

The problem I have is that App::TrainStatus.new returns nil from within
TrainFactory:

  def self.parse_message(msg)
    return App::TrainStatus.new
  end

If I change App::TrainStatus to another class which I haven't defined,
e.g. App::Foobar, I get an appropriate error.

If I insert the following line in to the code:

  puts App::TrainStatus

...then I get App::TrainStatus returned. If I put ".class" at the end, I
get "Class" returned - so it seems as though the class is loaded and
available.

What's puzzling me is that the TrainStatus class is loaded and available,
but a call to 'new' doesn't do anything - it doesn't even print the debug
message in the initialize() method of the class.

Can anyone give me some hints on troubleshooting?

Peter

--
Peter Hicks | Poggs Consultancy Services | t: 020 3095 2600 | m:
07970 476447

If that was a bug in Ruby it would be terribly broken. Can you reproduce
with a minimal example?

I am not sure: you would usually either access the class via
::App::TrainStatus or simply TrainStatus. It may be an edge case. Peter,
can you try out the two variants?

For the record this works for me in 2.0, too:

$ ruby -e 'class App; class TrainStatus; end; class TrainFactory; def
self.f; App::TrainStatus.new; end; end; end; p App::TrainFactory.f'
#<App::TrainStatus:0x000006004259b8>
$ ruby -e 'class App; class TrainStatus; end; class TrainFactory; def
self.f; TrainStatus.new; end; end; end; p App::TrainFactory.f'
#<App::TrainStatus:0x000006004259e0>
$ ruby -e 'class App; class TrainStatus; end; class TrainFactory; def
self.f; App::TrainStatus.new; end; end; end; p App::TrainFactory.f'
#<App::TrainStatus:0x000006004259b8>
$ ruby -e 'class App; class TrainStatus; end; class TrainFactory; def
self.f; ::App::TrainStatus.new; end; end; end; p App::TrainFactory.f'
#<App::TrainStatus:0x00000600425990>
$ ruby -v
ruby 2.0.0p598 (2014-11-13) [x86_64-cygwin]

Kind regards

robert

···

On Mon, Mar 16, 2015 at 11:16 PM, Xavier Noria <fxn@hashref.com> wrote:

If that was a bug in Ruby it would be terribly broken. Can you reproduce
with a minimal example?

--
[guy, jim, charlie].each {|him| remember.him do |as, often| as.you_can -
without end}
http://blog.rubybestpractices.com/

For what it's worth using both 2.2.0p0 and 2.2.1p85 what you describe seems
to work fine - as demoed in this gist:

Without seeing your actual script hard to know what the problem might be,
if nothing else check the spelling of initialize as I find that's a common
one for me to mis-spell (might explain your debug print not doing anything).

···

On 17 March 2015 at 07:44, Robert Klemme <shortcutter@googlemail.com> wrote:

On Mon, Mar 16, 2015 at 11:16 PM, Xavier Noria <fxn@hashref.com> wrote:

If that was a bug in Ruby it would be terribly broken. Can you reproduce
with a minimal example?

I am not sure: you would usually either access the class via
::App::TrainStatus or simply TrainStatus. It may be an edge case. Peter,
can you try out the two variants?

For the record this works for me in 2.0, too:

$ ruby -e 'class App; class TrainStatus; end; class TrainFactory; def
self.f; App::TrainStatus.new; end; end; end; p App::TrainFactory.f'
#<App::TrainStatus:0x000006004259b8>
$ ruby -e 'class App; class TrainStatus; end; class TrainFactory; def
self.f; TrainStatus.new; end; end; end; p App::TrainFactory.f'
#<App::TrainStatus:0x000006004259e0>
$ ruby -e 'class App; class TrainStatus; end; class TrainFactory; def
self.f; App::TrainStatus.new; end; end; end; p App::TrainFactory.f'
#<App::TrainStatus:0x000006004259b8>
$ ruby -e 'class App; class TrainStatus; end; class TrainFactory; def
self.f; ::App::TrainStatus.new; end; end; end; p App::TrainFactory.f'
#<App::TrainStatus:0x00000600425990>
$ ruby -v
ruby 2.0.0p598 (2014-11-13) [x86_64-cygwin]

Kind regards

robert

--
[guy, jim, charlie].each {|him| remember.him do |as, often| as.you_can -
without end}
http://blog.rubybestpractices.com/

That would not result in a nil response - it just does not initialize the
instance:

irb(main):003:0> class Foo; def intialize; @x=123; end end
=> nil
irb(main):004:0> Foo.new
=> #<Foo:0x0000060006e298>

One way to "achieve" the nil result would be to override #new for the class
in question.

Cheers

robert

···

On Tue, Mar 17, 2015 at 11:41 AM, Rhys Stansfield <r.stansfield@voc-8.com> wrote:

For what it's worth using both 2.2.0p0 and 2.2.1p85 what you describe
seems to work fine - as demoed in this gist:
Trainification · GitHub

Without seeing your actual script hard to know what the problem might be,
if nothing else check the spelling of initialize as I find that's a common
one for me to mis-spell (might explain your debug print not doing anything).

--
[guy, jim, charlie].each {|him| remember.him do |as, often| as.you_can -
without end}
http://blog.rubybestpractices.com/

Yeah I know it wouldn't return nil, I had considered that he might be
over-riding #new, but as I say, without seeing his script really hard to
know what the issue might be, especially as it apparently works on 2.1.5.

···

On 17 March 2015 at 10:44, Robert Klemme <shortcutter@googlemail.com> wrote:

On Tue, Mar 17, 2015 at 11:41 AM, Rhys Stansfield <r.stansfield@voc-8.com> > wrote:

For what it's worth using both 2.2.0p0 and 2.2.1p85 what you describe
seems to work fine - as demoed in this gist:
Trainification · GitHub

Without seeing your actual script hard to know what the problem might be,
if nothing else check the spelling of initialize as I find that's a common
one for me to mis-spell (might explain your debug print not doing anything).

That would not result in a nil response - it just does not initialize the
instance:

irb(main):003:0> class Foo; def intialize; @x=123; end end
=> nil
irb(main):004:0> Foo.new
=> #<Foo:0x0000060006e298>

One way to "achieve" the nil result would be to override #new for the
class in question.

Cheers

robert

--
[guy, jim, charlie].each {|him| remember.him do |as, often| as.you_can -
without end}
http://blog.rubybestpractices.com/