Error message, undefined method in Set

Hi,

I run some tests and get this:

  1. Error:
    test_construction(TestTask):
    NoMethodError: undefined method `include?’ for #Set:0x000001009aa2d0

the offending line of code is this:

@@available_classes << file unless @@available_classes.include? file

If I remove the unless @@available_classes.include? file then I still
get error messages, this time about << being undefined:

  1. Error:
    test_construction(TestTask):
    NoMethodError: undefined method `<<’ for #Set:0x0000010096a6a8

I checked the docs and Set has both of these defined, so I’m stumped as
to why this happens. It doesn’t happen when the application runs, it
runs fine, only when running the tests. I’ve added require 'set' to
the top of the test file but that didn’t help.

I’m running this through Ruby 1.9.2 on OSX 10.6.4

Any help on this is much appreciated, as I’ve no idea what to try next.

Regards,
Iain

Iain B. wrote:

Any help on this is much appreciated, as I’ve no idea what to try next.

It is possible that there is another Set class defined somewhere. Try:

puts Set.to_s # does this show “Set” or “Foo::Set” ?

assert_equal Set, ::Set, “Using Set not at the top level!”

Otherwise, you could copy your test file to another name, and keep
trimming it until you get the smallest possible file which reproduces
the problem, then post that file here.

I don’t recognise “test_construction(TestTask)” so I don’t know what
test framework you’re using. Good ol’ Test::Unit looks fine to me:

require ‘test/unit’
require ‘set’
class TestSet < Test::Unit::TestCase
def test_set
set = Set.new
assert_nothing_raised do
set << 1
set << 2
end
assert set.include?(2)
assert !set.include?(3)
end
end

Started
.
Finished in 0.000752 seconds.

1 tests, 3 assertions, 0 failures, 0 errors

On Mon, Sep 27, 2010 at 3:55 PM, Brian C. [email protected]
wrote:

Iain B. wrote:

Any help on this is much appreciated, as I’ve no idea what to try next.

It is possible that there is another Set class defined somewhere.

Would be my guess as well. I would rather try this to get an idea of
what class @@available_classes is an instance of:

p @@available_classes.class, @@available_classes.class.ancestors

It’s likely that we see delegator at work here:

irb(main):010:0> require ‘delegate’
=> true

irb(main):016:0> dd = SimpleDelegator.new ::Set.new
=> #<Set: {}>
irb(main):017:0> dd.to_s
=> “#Set:0x10154174
irb(main):018:0> dd.class
=> SimpleDelegator
irb(main):019:0> dd.class.ancestors
=> [SimpleDelegator, Delegator, Object, Kernel, BasicObject]

Note item 17 which looks suspiciously similar to what OP posted.

Still:

irb(main):020:0> dd.include? 123
=> false

Which would not yield the original error.

Try:

puts Set.to_s # does this show “Set” or “Foo::Set” ?

This tells you only about Set but you do not know what class created
@@available_classes.

assert_equal Set, ::Set, “Using Set not at the top level!”

Kind regards

robert

On 27 Sep 2010, at 14:55, Brian C. wrote:

It is possible that there is another Set class defined somewhere. Try:

puts Set.to_s # does this show “Set” or “Foo::Set” ?

It shows Set

assert_equal Set, ::Set, “Using Set not at the top level!”

This passed.

On 27 Sep 2010, at 15:02, Robert K. wrote:

… I would rather try this to get an idea of
what class @@available_classes is an instance of:

p @@available_classes.class, @@available_classes.class.ancestors

Set
[Set, Enumerable, Object, Kernel, BasicObject]

I played around with a few things, and it turns out that this works
(whether at the top of the test file or another file that does all the
requiring) :

require ‘set’
require ‘choice’ #this is the class that utilises Set

but this throws errors:

require ‘choice’
require ‘set’

I’m very surprised that the order of requires (at the top of a file) can
affect anything in this way. Is this the way it’s supposed be? If not,
what could be the cause?

The Choice class itself doesn’t have any requires in it, btw, that’s all
done in a separate file for all the app.

Regards,
Iain

Iain B. wrote:

but this throws errors:

require ‘choice’
require ‘set’

Then at the top of choice.rb I’d put require ‘set’.

I’m very surprised that the order of requires (at the top of a file) can
affect anything in this way. Is this the way it’s supposed be? If not,
what could be the cause?

It can be. Imagine this:

— set.rb —
class Set < Hash

end

— choice.rb —
class Set
… add some more methods to the class
end

If you require choice.rb first, you would get an exception when
requiring set.rb

Iain B. wrote:

Then at the top of choice.rb I’d put require ‘set’.

That’s what I was originally doing, but a lot of the advice I’ve read on
structuring projects is to remove the requires from individual
classes/files and put them in a central file with the name of the app
under lib.

Personally I don’t support that advice, but it’s very much a matter of
personal preference. I like each source file to declare its
dependencies, because it lets them be re-used more easily, although it
is easy to miss some.

I don’t know why in your case you have to require set.rb before
choice.rb. If you could boil choice.rb down to a small test case which
demonstrates the problem, it should be fairly easy to identify. But
without seeing the code, I’m only guessing.

On 28 Sep 2010, at 07:11, Brian C. wrote:

Iain B. wrote:

but this throws errors:

require ‘choice’
require ‘set’

Then at the top of choice.rb I’d put require ‘set’.

That’s what I was originally doing, but a lot of the advice I’ve read on
structuring projects is to remove the requires from individual
classes/files and put them in a central file with the name of the app
under lib.

end

— choice.rb —
class Set
… add some more methods to the class
end

If you require choice.rb first, you would get an exception when
requiring set.rb

Ok, thanks. It’s good to know gotchas!

Regards,
Iain

On 28.09.2010 22:13, Brian C. wrote:

dependencies, because it lets them be re-used more easily, although it
is easy to miss some.

+1

I don’t know why in your case you have to require set.rb before
choice.rb. If you could boil choice.rb down to a small test case which
demonstrates the problem, it should be fairly easy to identify. But
without seeing the code, I’m only guessing.

Basically order should not matter. It seems choice.rb or some file
required from there does something bad to Set like you showed in your
example. Although, if I think about it: that should be visible:

$ ruby19 -e ‘class Set;end; class Set < Hash; end’
-e:1:in `’: superclass mismatch for class Set (TypeError)

Set could be reassigned but even then that would be visible

$ ruby19 -e ‘class Set;end; Set = Class.new Hash’
-e:1: warning: already initialized constant Set

Ian, if you really want to know what goes on you could try this at the
top of the script, before any requires:

set_trace_func lambda {|*a| p a}

This will create copious output though.

Kind regards

robert

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs