# Newbee question. Runtime classloading

**URL:** <https://www.ruby-forum.com/t/newbee-question-runtime-classloading/183293>\
**Category:** Ruby\
**Created:** [February 11, 2010, 9:47am UTC](https://www.ruby-forum.com/t/newbee-question-runtime-classloading/183293 "2010-02-11T09:47:47Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![holod](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/85f322/32.png) [@holod](https://www.ruby-forum.com/u/holod)\
**Post date:** [February 11, 2010, 9:47am UTC](https://www.ruby-forum.com/t/newbee-question-runtime-classloading/183293/1 "2010-02-11T09:47:47Z")

</div>

Hello, I’m Java developer and now explore Ruby for increasing  
programming knowledge. I want to understand runtime class loading

I have an application:  
/lib/parser\_factory.rb  
class ParserFactory  
end

/lib/parser\_format\_x.rb  
class ParserFormatA  
end  
/lib/parser\_format\_y.rb  
class ParserFormatB  
end  
/lib/parser\_format\_z.rb  
class ParserFormatC  
end

ParserFactory gets file and decides which parser to initialize and use.  
I have such code in ParserFactory:  
clz = “ParserFormat#{@version}”  
parser\_impl = Kernel.const\_get(clz)  
and I get an error:

Test-unit version : 2.0.1 loaded

1. Error:  
test\_parsing(ParserTest):  
NameError: uninitialized constant Kernel::ParserPlanFormat1\_0  
D:/Ruby\_1\_86\_27/lib/ruby/gems/1.8/gems/rake-0.8.1/lib/rake.rb:2237:in  
`const\_missing’

I don’t get how I have to specify path to class. I’ve tried it as in  
Java: “parsers/SomeClass”, but it didn’t help 🙂

Also i’m exploring Ruby on Rails and  
Kernel.const\_get(“MyFavouriteModelClass”) works there.

Please explain or give guide to read.

---

<div class="post-metadata">

**Author:** ![holod](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/85f322/32.png) [@holod](https://www.ruby-forum.com/u/holod)\
**Post date:** [February 11, 2010, 10:13am UTC](https://www.ruby-forum.com/t/newbee-question-runtime-classloading/183293/2 "2010-02-11T10:13:31Z")

</div>

Ruby needs to interpret the file where the class is defined before you  
can use it. Interpreting the file has the side-effect of defining the  
constant, which is in turn a side-effect of the class keyword.

As you surely know that is typically done with require, and if the  
parsers are unknown beforehand you can just use Dir[] with a glob to  
require whatever has some filename pattern in a loop or something. I  
mean, require is a method you can call it wherever you want.

Rails does not need that because it offers class/module autoloading:  
if the filename is named after the class using some common sense  
conventions, and lives in some of the standard directories,  
app/something, lib, etc., then the dependencies mechanism goes and  
loads it for you the first time the constant is used. That is  
accomplished basically via a Ruby hook called const\_missing that is  
triggered when that initial failure happens.

---

<div class="post-metadata">

**Author:** ![holod](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/85f322/32.png) [@holod](https://www.ruby-forum.com/u/holod)\
**Post date:** [February 11, 2010, 10:32am UTC](https://www.ruby-forum.com/t/newbee-question-runtime-classloading/183293/3 "2010-02-11T10:32:12Z")

</div>

Xavier N. wrote:

> Ruby needs to interpret the file where the class is defined before you  
> can use it.  
> I understand it.

> Interpreting the file has the side-effect of defining the  
> constant, which is in turn a side-effect of the class keyword.  
> don’t get idea with side-effects

> As you surely know that is typically done with require, and if the  
> parsers are unknown beforehand you can just use Dir[] with a glob to  
> require whatever has some filename pattern in a loop or something. I  
> mean, require is a method you can call it wherever you want.  
> Something like:  
> require “parsers/parser\_format#{@format\_version.gsub(/./, ‘_’)}"  
> clz = "ParserFormat#{@format\_version.gsub(/./, '_’)}”  
> parser\_impl = Kernel.const\_get(clz)  
> works nicely!

> Rails does not need that because it offers class/module autoloading:  
> if the filename is named after the class using some common sense  
> conventions, and lives in some of the standard directories,  
> app/something, lib, etc., then the dependencies mechanism goes and  
> loads it for you the first time the constant is used. That is  
> accomplished basically via a Ruby hook called const\_missing that is  
> triggered when that initial failure happens.  
> Thanks!

---

<div class="post-metadata">

**Author:** ![holod](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/85f322/32.png) [@holod](https://www.ruby-forum.com/u/holod)\
**Post date:** [February 11, 2010, 10:56am UTC](https://www.ruby-forum.com/t/newbee-question-runtime-classloading/183293/4 "2010-02-11T10:56:49Z")

</div>

On Thu, Feb 11, 2010 at 10:32 AM, Sergey S.  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > Interpreting the file has the side-effect of defining the  
> > constant, which is in turn a side-effect of the class keyword.  
> > don’t get idea with side-effects

Ah yes let me explain a bit more. Doing

```
class C
end

```

as far as constants and class names is concerned is similar to doing  
this

```
C = Class.new

```

By the way, top-level constants are stored in Object. Your code works  
with Kernel because it is mixed in Object and constant lookup goes up,  
but Object would be the natural place to invoke const\_get on.

> Something like:  
> require “parsers/parser\_format#{@format\_version.gsub(/./, ‘_')}"  
> clz = "ParserFormat#{@format\_version.gsub(/./, '_’)}”  
> parser\_impl = Kernel.const\_get(clz)  
> works nicely!

That’s right.

---

<div class="post-metadata">

**Author:** ![holod](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/85f322/32.png) [@holod](https://www.ruby-forum.com/u/holod)\
**Post date:** [February 11, 2010, 1:01pm UTC](https://www.ruby-forum.com/t/newbee-question-runtime-classloading/183293/5 "2010-02-11T13:01:21Z")

</div>

Xavier N. wrote:

> as far as constants and class names is concerned is similar to doing  
> this
> 
> ```
> C = Class.new
> 
> ```

Nice opportunity to make silly mistakes, especially if you work in group  
with low communication.  
Thank you for explaining me the material.

---

<div class="post-metadata">

**Author:** ![holod](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/85f322/32.png) [@holod](https://www.ruby-forum.com/u/holod)\
**Post date:** [February 11, 2010, 4:36pm UTC](https://www.ruby-forum.com/t/newbee-question-runtime-classloading/183293/6 "2010-02-11T16:36:21Z")

</div>

> Xavier N. wrote:

Excuse me for disturbing you again.  
I have pretty close question.  
I don’t get how to locate files inside ruby-project. In Rails I’ve used  
‘RAILS\_ROOT’ and it was clear to me how does it work.  
And what about usual ruby app?

1. NetBeans generated TestUnit gets this string:  
$:.unshift File.join(File.dirname( **FILE** ),’…’,‘lib’)  
What for?

2. My project structure:  
project:  
\lib  
\lib\main.rb  
\lib\some\_file.rb  
\lib\parsers\yaml\_parser.rb  
\data  
\data\yaml\_parser\_config.yml  
\data\source.scv  
\data\Format\_1.0.yml

I keep config files in ‘data’ catalog.

Is it good way to ref these resources in this way:

#Some TestUnit  
def test\_read  
@conf = YAML.load\_file( ‘data/Format\_1.0.yml’ ) #Good or bad?  
assert\_equal(Hash, @conf.class)  
assert\_equal(“Dates”,@conf[‘Dates’][‘class’])  
assert\_equal([“id”, “descr”, “rough\_est”, “accurate\_est”, “spent”,  
“left”, “resource\_id”, “begin”, “end”],@conf[‘Tasks’][‘fields\_ordered’])  
end

or in some Parser class:  
@parser\_config = YAML.load\_file(‘data/Format\_1.0.yml’ ) )

Or I have to use some ‘magic’ ruby variables?

---

<div class="post-metadata">

**Author:** ![holod](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/h/85f322/32.png) [@holod](https://www.ruby-forum.com/u/holod)\
**Post date:** [February 11, 2010, 5:23pm UTC](https://www.ruby-forum.com/t/newbee-question-runtime-classloading/183293/7 "2010-02-11T17:23:12Z")

</div>

Yes you have the **FILE** keyword. That evaluates to the filename of  
the file that contains it. So, its value is per file.

In a case like yours it is normal to rely on **FILE** and a known  
project structure to go for stuff thus avoiding config files.
