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:
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.
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!
On Thu, Feb 11, 2010 at 10:32 AM, Sergey S. [email protected] 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.
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?
NetBeans generated TestUnit gets this string:
$:.unshift File.join(File.dirname(FILE),’…’,‘lib’)
What for?