On Saturday 23 August 2008 18:47:37 Todd C. wrote:
The only other difference I can find is that if the class doesn’t
previouly exist, class_eval on the class will cause an error.
More accurately, if the class doesn’t previously exist, trying to access
(via class_eval) will call const_missing on the parent module (usually
Object, I think?), and it’s const_missing that throws the error. (This
important, I promise.)
The “class” syntax will define the class if it doesn’t exist, and reopen
ActiveSupport (and thus, Rails) does autoloading by overriding
const_missing – which means that when you do this:
If Foo wasn’t available, Rails will actually try to autoload a file
called ‘foo.rb’, somewhere in its autoload path. Then, if that file
define Foo::Bar, it’ll go looking for ‘foo/bar.rb’, again in that path.
If, instead, you decide to do this:
In that case, if Foo isn’t available, you’re defining it right there!
means that instead of everything foo.rb presumably defines, you’re
nothing but what you’ve actually put between “module Foo” and “end”…
Which is a completely silent error until you decide to actually load
in which case, the only error you’ll get is if you thought Foo was a
and it was actually a class.
Now, this probably isn’t a problem with ActionController, since, being
that’s probably always available.
But if there’s going to be autoloading anywhere in the project, I
a best practice to only use “class” or “module” once, where you intend
originally define the class (or module) in question. If you need to
to monkeypatch, use _eval.
The same is NOT true of “autoload”, by the way. (Seems to be in 1.9, not
what versions of 1.8.) That is, if you say:
autoload :Foo, ‘foo’
This will actually work the way you expect.
There are other problems with autoload, though – it doesn’t support
overridden require commands, nor does it provide any other means of
extensibility beyond modifying the global require path.