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.
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
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.
... 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
···
On 27 Sep 2010, at 14:55, Brian Candler wrote:
On 27 Sep 2010, at 15:02, Robert Klemme wrote:
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
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.
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
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.
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.
+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 `<main>': 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: