On Wed, Mar 21, 2012 at 20:48, Xavier Noria <fxn / hashref.com> wrote:
> On Wed, Mar 21, 2012 at 8:17 PM, Nikolai Weibull <now / bitwi.se> wrote:

> Take into account that #feature? assumes the argument matches the constant
> name, which may not be the case. For example
>
>   module A
>    module B
>    end
>   end
>
>   module C
>    D = A::B
>   end
>
> In that code A::B and C::D are defined constants that store the same module
> object, but #feature? returns false on C::D.

True, but #feature? wasn°«t written to take such things into account.

> It would be more correct to rely on const_defined? like Active Support does.

There°«s a timing issue with using const_defined? followed by const_get
instead of calling const_get directly and catching NameError.  Also,
using const_defined? won°«t invoke const_missing, which might set the
constant for you, if that°«s what you want to have happen.

I guess

def feature?(path)
   path.split('::').reduce(Object){ |o, e|
     c = begin o.const_get(e); rescue NameError; return nil end
     return nil if c == (o != Object and begin Object.const_get(e);
rescue NameError; nil end)
     c
   }
end

might work, as it tries to make sure that we don°«t return to the top
level at any point in the path resolution, but is a lot more
complicated than I think that it should have to be.