[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Class_eval vs. reopening class

Todd Corenson

8/23/2008 10:08:00 PM

I asked a similar question to this in the Rails forum, but it's pretty
generic to Ruby:

Is the only difference between these the scoping or is there something
more?

ActionController::Base.class_eval do
include ActionController::Flash
include ActionController::Filters
...
end

class ActionController::Base
include ActionController::Flash
include ActionController::Filters
...
end
--
Posted via http://www.ruby-....

3 Answers

Todd Corenson

8/23/2008 11:48:00 PM

0

Todd Corenson wrote:
> I asked a similar question to this in the Rails forum, but it's pretty
> generic to Ruby:
>
> Is the only difference between these the scoping or is there something
> more?
>
> ActionController::Base.class_eval do
> include ActionController::Flash
> include ActionController::Filters
> ...
> end
>
> class ActionController::Base
> include ActionController::Flash
> include ActionController::Filters
> ...
> end

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.
--
Posted via http://www.ruby-....

David Masover

8/24/2008 1:40:00 AM

0

On Saturday 23 August 2008 18:47:37 Todd Corenson 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 it
(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 is
important, I promise.)

The "class" syntax will define the class if it doesn't exist, and reopen it if
it does.

ActiveSupport (and thus, Rails) does autoloading by overriding
const_missing -- which means that when you do this:

Foo::Bar.class_eval do
...
end

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 doesn't
define Foo::Bar, it'll go looking for 'foo/bar.rb', again in that path.

If, instead, you decide to do this:

module Foo
class Bar
...
end
end

In that case, if Foo isn't available, you're defining it right there! Which
means that instead of everything foo.rb presumably defines, you're getting
nothing but what you've actually put between "module Foo" and "end"...

Which is a completely silent error until you decide to actually load foo.rb,
in which case, the only error you'll get is if you thought Foo was a module,
and it was actually a class.

Now, this probably isn't a problem with ActionController, since, being Rails,
that's probably always available.

But if there's going to be autoloading anywhere in the project, I consider it
a best practice to only use "class" or "module" once, where you intend to
originally define the class (or module) in question. If you need to reopen it
to monkeypatch, use _eval.



The same is NOT true of "autoload", by the way. (Seems to be in 1.9, not sure
what versions of 1.8.) That is, if you say:

autoload :Foo, 'foo'
class 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.

Todd Corenson

8/24/2008 9:25:00 AM

0

Thanks, David for your reply. I kind of expected there was some magic
going on, otherwise why bother?

--
Posted via http://www.ruby-....