views:

160

answers:

2
Module M
    Class C
    end
end

What I need is something like:

M.was_defined_here?(M::C)
M.classes.include?(M::C)

Does this exists somehow?

I know I could parse M::C.name. But someebody could have the idea to change Module#name, to make it more astetic or something. I want a clean solution.

+3  A: 
M.constants.map {|c| M.const_get(c)}.include?(M::C)

Or, from johannes' comment, using find (will perform better if the class does exist in M and doesn't happen to be the last constant in M - though it should rarely make a measurable difference):

M.constants.find {|c| M.const_get(c) == M::C }

Edit: Since you actually just want a boolean result, this any? makes more send than find:

M.constants.any? {|c| M.const_get(c) == M::C }
sepp2k
I think M.constants.find { |c| M.const_get(c) == M::C } performs better.
johannes
Good point. I'll add it to the answer.
sepp2k
A good start, but it won't work if M::C doesn't exist at all.
James A. Rosen
The problem, as I understood it was: Input: a class object and a module object. Output: Whether the class is defined inside the module. So, at least from my understanding of the problem description, the class has to exist.
sepp2k
sepp2k understood the question the way I meant it.
johannes
If you know that `M::C` exists, then what are you testing? You won't be able to tell the difference between a class `C` that was declared within `M` and one that was declared elsewhere but `M` adds it to its namespace.
James A. Rosen
Gaius: My understanding is that `M.was_defined_here?(M::C)` should return true and `M.was_defined_here?(String)` should return false. So `M.was_defined_here?(someobj.class)` should return true if and only if obj is an instance of one of the classes defined in M.
sepp2k
+2  A: 

sepp2k's answer won't work if M::C is not defined at all, since Ruby will raise a NameError in that block.

Try this:

M.constants.include?('C')

If you're worried that you have a reference to M::C by a different name, like so:

module M
  class C
  end
end

MY_M_C = M::C

then you can test whether MY_M_C is the same as M's C like so:

M.constants.include?('C') ? MY_M_C == M.const_get(:C) : false
James A. Rosen
why not use `M.const_defined?(:C)` instead?
banister
That'll work just as well and will perform at least as well as mine. Nice one.
James A. Rosen