Video summary
The video provides a deep dive into Ruby on Rails' constant autoloading mechanism, explaining how it eliminates the need for manual `require` statements by automatically loading classes and modules on demand. The speaker begins with a technical refresher on Ruby constants, clarifying that they are essentially objects stored in a module's constant table rather than immutable values. He demonstrates that defining a class or module is syntactic sugar for creating an anonymous object via `Class.new`, assigning it to a constant, and then setting its name within the interpreter. This foundational understanding is crucial because autoloading relies on these internal structures to resolve names dynamically without restarting the server during development.
The core of the talk focuses on the resolution algorithms that Rails uses to locate missing constants. When a constant is accessed but not found in the current scope, Ruby triggers a `const_missing` hook which searches through predefined autoload paths like `app/models`, `app/controllers`, and `app/helpers`. The system attempts to find a file matching the constant's name within these directories; if a directory exists without an `.rb` file, Rails assumes it defines a module rather than a class. A significant portion of the presentation addresses the limitations of emulating this behavior manually, noting that Rails cannot perfectly replicate Ruby's complex nesting rules or handle anonymous modules created via `eval`. Consequently, the framework operates under a specific contract where developers must follow naming conventions and directory structures to ensure reliable loading.
Finally, the speaker explains how constant autoloading interacts with the request lifecycle and caching strategies in different environments. In development mode, Rails uses file watchers to detect changes and wipe constants from memory upon modification, ensuring that updated code is loaded immediately without a server restart. In production, while autoloading still occurs, it is executed during the boot process rather than on every request to optimize performance and avoid thread-safety issues inherent in dynamic loading. The talk concludes by discussing configuration options for excluding certain directories like `lib` from automatic reloading and answering questions about namespace resolution, reinforcing that Rails' approach prioritizes developer convenience through strict adherence to idiomatic file organization over generic constant resolution rules.
Read the full video transcript
[Applause]
okay thank you
so this talk is about constant
autoloading and ruby on rails
so if if ruby on rails were like normal
ruby applications
you know that if you want to use
application controller here
and you want to use the post model here
you should require you know the files
where they are defined and uh this is
inconvenient because
if you require then uh you know
require only loads file one time so you
you should need to
restart the server something like that
and if you instead of require use
load then you are going to to execute
the file each request you know
redefining constants and doing all kind
of weird stuff
and in the end it's kind of you know
it's there's some redundancy here right
so you know that ruby on rails uh allows
you
not to do these things and indeed it's
the the idiomatic way to
to write not to put requires so this
thing
it's you know it's automatically load
and this thing is automatically for you
if needed
so the the talk is about how this works
and it has three sections first section
it's a
constant refresher because constant
autoloading is like a
technical topic that eats everything
about constant so
we we should have constants you know
fresh
in our minds which are the rules called
the recovery work
then we are going to to see how constant
auto loading
actually um is done and
after that the third section is about
the the request
flow how how do we get
the constants out a lot and then how we
get the classes out to load
you know because in development mode if
you change the file
then the changes automatically without
restarting the server
afresh in your application and that kind
of fast so how does that work
constants you all know constants you are
ruby primers so
you know they are kind of like a global
thing that
that is just like a variable but it's
supposedly not
um going to change actually you know the
ruby allows you to change the constants
but that's like
a negative thing so you know what
constants are
and this thing is also a constant
assignment
like we in the slide we said before
and uh
some people do not recognize this as a
constant assignment because you have the
class keyword this kind of stuff
so but indeed that's like that's just
syntactic sugar for a constant
assignment
that's creating a class object because
you know in ruby everything is
objects it's like there's a small set of
actions and everything it's you know
derived from those actions
so in ruby we have modules and class
objects and we have constants
and they like kind of work together but
they are like very very
decoupled things indeed so when you use
the class keyword
you want ruby it's constructing a
class object and it's storing that class
object in the c
constant it's the same thing in this
slide
we are starting one in the x in the x
constant
so here what happens is that there's a
class new thing going on behind the
scenes
and being stored in the c constant
so basically what happens is this behind
the scenes that's that's for real
so that's a normal class definition
class c
inherits from d and includes a module
let's put that example
so what this thing is doing not
technically equivalent but equivalent
for the purposes of this talk is this
thing
which is class new class new gives you a
class object which is anonymous
it's just creating a class object like
you could have a new string
right inherits from d and includes
m and then the the the result of this
expression is a class
object which has no name and after that
if you assign that to a constant and you
see clearly here's a constant assignment
like x equals one right it's a constant
assignment
so if you then assign to c
then you are getting in c an object
because c
is not this is not syntax this is a
constant like it could be a variable so
this is a constant
when you evaluate this expression it
uses
a class object that responds to the
to the name method and that gives you c
y gives you c if we if we define it an
anonymous
class because that's the way that the
way the interpreter
works the interpreter when he is
executing a constant assignment it has
code
that manually says if the thing that you
are going to assign to a constant
it's a class or a module and the class
or module are anonymous
i am going to set the name that point
and that name is set in stone and
it's not going to change anymore but
that's happening when you say
when you use the class module keyword
that's what happens behind the scenes
so these things that we all take for
granted
they are constants they are not classes
so properly speaking
hash is not a class like this thing
is not a class this thing is a constant
that happens to a store
the built-in thing that it's a class for
uh you know that models hash tables you
know
so when we say the hash class the string
class
and we write it like this we are doing a
little abuse of language
because what we really mean here is that
the
class object that it's stored in the
in the hash constant and the same with
the user model
and that kind of thing so um they are
regular objects and you can you can pass
them around
store them in other constants variables
pass them as
arguments to methods you can do all
kinds of things so ruby has no syntax
for class names
it's all constants
and constants are starting modules
constantly it's a very big topic i have
like
a long long talk only talking about
constant so this is a refresher
where i selected like the the the
minimal
topics that uh we need to cover in order
to
you know to be able to follow the follow
the the next sections
so this is a snippet from
venus where the module class
is implemented and you see the the
module class
has a constant table so constants
belong to modules in a in a very literal
way you know
there's an actual constant table which
is like a hash table you can
think about it like a symbol table you
know
that stores constants and associates the
constants
to their value you know so constants
belong to modules and top level
constants belong to object
so when you are doing this thing
what you are doing actually is it's
creating an
entry in that table so the table that
module m
has now it's going to have an appear
which is x mapped to one
right it's that's the way it works and
uh let's let's let's say it again
this thing is a constant assignment so
we have module xml class sax parser
so this thing is a constant assignment
and
this is equivalent to doing this thing
so class new
assigned to such person you see this
node
it's equal i mean it looks the same as
this thing
you know apparently they are kind of
different things but they are not
so this thing we write it this way it's
equivalent
to this other thing so what's
this doing the same thing this is doing
this is
storing a sax parser constant
in the constant table of the object
that it's stored in the xml constant
so if we spell everything what's
happening here that's the whole story
and you know there's a constant api so
we have
cons get cons set remove cons
you can ask for the constants of so that
whole api
it's um uh manipulating that table
so cons set it's you know like creating
uh you know and entering that in the
symbol table cons get
is like a hash fetch you know so the
constant api
is about those tables and those tables
are per module
so every module in all your application
has its own table and you can manipulate
that individual table with
this api
i wanted to cover now the constant
resolution algorithms because
that's crucial to a constant autoloading
how constant autoloading is resolved
so we have actually three algorithms in
ruby for constant name resolution
first one is this so uh
x equal one is storing the x the x
constant
somewhere where in the table of m
that's clear right so m is the module in
a scope let's
let's say that way and this x is
stored in that constant table
here let's say it again this is a
constant assignment
class uses controller so where is user
controller being
stored that's very important so the
the algorithm here is the same for the x
uh
with one tweak that it's in in the
implementation of the class keyword
so i'm sorry
right so the thing here is
the the interpreter says do i have
a constant called users controller
in the admin module if i have that
constant
that should yield a class object i will
check it
and if everything looks right we are
going to reopen
that class object right so
that it's looked up in the constant
table of module at me
if i don't have it in that constant
table we are going to define a new class
and the constant that's defined as a
side effect of that
class keyword execution is going to be
stored in the constant table
of modular mean that's very important
because if this algorithm was similar
to the to the following algorithms we
are going to explain but you already
know
uh and and for instance if if
the algorithm look it up this constant
house also
you know in the in the global name space
we are because
then we we would depend on the loading
order of things you know
so this user's controller even if we if
we have a top level usage controller
there's not going to be any problem
because even if there's a user
controller in the top level here
define it at that point of execution is
not going to be found so
it's it's a strict it looks looks at in
the constant table of that module and
if it doesn't exist in that table you
are going to define a new class
then second um resolution algorithm is
this one when you have a a constant path
there's no
well-defined terminology for this team
so fully qualified name
constant path several you know jargon
going on in the community
but let's do it let's say this is a
constant path so
when you when you have this thing if
this is this um
okay so what happens here is that x is
looked
up in the constant table of m and if
it's not
found then you go up the ancestors of m
looking in the constant tables right
that's what happens here
and the third thing is the generic one
which is the i guess
statistical is the one that most people
use which is that you have an x here
without any qualification and that's the
generic thing and that goes this way
i call it the 10 o'clock rule meaning
that we are going to
do to go to the 10 and then we are going
to go
up to 12. that means we are going to
check
x in c does it belong to the constant
table of c
no let's suppose that the the answer is
no
we are going upwards to the to the
uh outer scope this is technically
called the nesting so from c
if it's not in c we are going to check
the constant table of
n it's the constant table so if n has
ancestors
they are going to be ignored so we are
going to check the constant table
if it's not in n then we are going to
check m
if m doesn't happen to have the constant
either then we are going to check
the ancestors of c and
there's a little trick here because if c
instead of a class was a module
then there's the object object does not
belong to the ancestors of molecule
of molecules then there's a manual thing
in the interpreter written
that says if we are if this you know
this uh most nested time space is a
module
then we are going to check object by
hand
in the case of classes no because in the
case of classes
until 1 9 you have always object in the
ancestral chain
so actually in one line we have basic
object and finding things happening with
basic object because
if you subclass directly basic object
object does not belong to the ancestors
of
of your class and then you can if you
cannot even
use the object constant there or the
string constant
like you know like in a relative name
why
because object and string are not global
classes or anything
like that they are regular ruby
constants and they follow the resolution
algorithms
and since object is not you know in the
change of things we are going to check
they are not found so you have to do a
column column thing
here to you to convert that relative
name
to an absolute path and say hey we are
going to look
this up in object all right so that's
the constant refresher
and we are now going to cover constant
auto loading
consonant loading remember uh we don't
need to
require this thing it's it's it it all
happens you know on the fly
so here's the thing there's a in the
constant api
there's a thing called cons missing cons
missing is a hook
that it's called if you are in trying to
access
a constant in some within some
particular module
and that constant constant is not there
and
well so the resolution algorithm that i
mentioned before
if they fail to find the constant
there's there's another loop
and calls cons missing on the most
nested thing
right so that's the complete algorithm
you you you call constant
consuming consuming has this information
has you sorry uh
okay all right uh here so
we have the name of the module
that it's game you know that that it's
uh who's consuming is being triggered
you have the name this is this is a
class you know the class method that
that says the name of yourself the class
and module
and for instance in that case the name
would return the string
at mean column column user controller
this is a string
right and then we have the cons the cons
name the cons name
that you know that triggered this thing
and well in nine one nine is
pass it as a symbol but that's not
important you have the name somehow
so that's that's the two pieces of
information you have about what happened
so active support has this uh set of
directories
uh which is uh which is called autoload
paths in range
three one i think and before it was
load path but it was renamed and auto
loadpass
by default has all the subdirectories of
adb
so app models app controllers uh avp
helpers
and if you throw any subdirectory there
it's picked up
automatically presenters or whatever you
would like to have there observers
whatever
so auto lock ha a path has this indeed i
said
set but it's an array because the order
is important so let's say
it's an array and what happens is this
so the situation is that uh we are here
we are here at modular mean class uses
controller
and then uh let's let the examples
is how we auto load the user constant
that's the example we are going to
we are going to to see so um which this
is the information
and this is what happens uh first
we we look over all all these
directories all the autolog parts
and append to the directory this this
uh you know this uh suffix
so if i append at mean slash
user's controller slash user will be is
there a file there
let's suppose the answer is no so we are
going to backtrack
and the track uh tests
whether there is a directory without rb
which is something i am going to cover
uh later on so let's forget this one
and then there's there's some
assumptions and trade-offs here
that are very important that i am going
to explain that
they are not assumptions written in the
code they are implicit assumptions that
happen at that point
that allow us you know to to to continue
looking for the outlook path then you
you look for admin user
no let's suppose we are going to find a
global user like which is the normal you
know
the normal situation right but you
active support tries
admin user b if it doesn't exist back
track
and tries also to find a directory i'm
going to explain it why
then there's another set of assumptions
here that i
implicit and finally if
everything is normal there's a user will
be top level somewhere
probably in app models and it's found
it's load right so it's load it returns
the the the class
whose name is user and your
action whatever is executed so that's
what happens
and we are trying uh these things
here's the thing with the directories
and
let's suppose we have here let's let's
suppose we have
some workers and we have uh organized
our workers in a work directory so for
instance you have
a worker and then inside worker
event register and perhaps you have you
have other workers
for some key or something okay so
in a constant path constants are single
names so
uh all right so here in a constant path
we have
two constants so this isn't worker even
register
is not is not processed like like a
single unit
they are two constants and the thing is
that
uh you look it up the the worker
constant and then
inside that module you're going to find
event register so
we we need first to find worker
and worker is autoload one out when
autolog
comes back with worker load
then const missing is still great for
event register
and the same algorithm runs for event
register so there are two autolots here
so the first part a lot is worker and if
if you think
in order to have the the worker name
space defined
you do not need to to write a worker dot
rb
right you organize your workers in a
work directory but you don't
need to to write a worker every file
in order to define the worker module
if you have it it will be executed it
will be fine found and executed but
you don't you don't need that and so
yeah so if worker rv is not is not a
phone then the direct the work directory
is look it up and
if it's phone what happens is that
active support defines a module for you
so it does this
in this case of a worker would we assume
that
it's top level thing so object is going
to have defined
module new and this is assigned to
worker and and this is a constant
assignment
therefore this module new which at this
point of the
of of the execution is anonymous it's
going to end up
after this car this call it's finished
is going to be
to end up having a worker name so it's
apparently everything it's as it was
defined in the you know in the file
system
when this happens uh we we keep
track to of a couple of things one is
uh the fully qualified names of
constants
you have autoload why do you do you keep
track of that because we want to be able
in development mode
to and undo this thing and you know and
so that if you change the file and user
will be
you are going to to have this refreshed
so
we are going to see later how do we work
do we
use this information but um
uh so this this there's some watchers
that monitor
new constants coming in after the
execution of the everything
and they you know they store that
information for later use
and also they saw the file names the
file names are used
to detect uh circular secular you know
constants
uh autoloading going on
all right and kernel load and kernel
require
are decorated by active support
why because
if you love the user constant
executed executing the user will be
filed and
the user rb file happens to require no
cohidi
while you are watching the new constants
that are coming
you should be able to say hey nokogiri
is a new constant but that was
was not outlawed right
so uh there's a you know there's a stack
of watchers that are pushed by active
support while these things happen
that are able to say yes these constants
are relevant we are going to store
these ones this car then there's a stack
there's a stack of watches that
are you know popping and pushing
and that the taker of these things
so you can autoload user you can require
nokogiti there
and active support is able to
distinguish between the two
of them and same thing for for load
okay this is the way it works
and this is not the constant resolution
algorithm
why because you cannot write you can you
cannot emulate
constant resolution algorithms with cons
missing
the first the first problem is nesting
you don't you do not have nesting
information
and nest the nesting which is the the
you know
which reflects the scope the name spaces
you have nested at the point where the
constant was missing
uh um is not passed to the cons missing
uh hook in the commission hook you know
who am i and i know which is the
constant that is missing
but there's no more information so
in this example we have we have three
three different nestings
the first one is the regular one right
and and
so in at this point the next thing is m
n
m which is you know the name spaces we
have
but then if you do model um a module
sorry
m n the next thing is just mn there's no
m so active support is going to
find uh in m and
user v if it doesn't find it it tries
m user v and if it doesn't find it tries
objective emerald
but in this case it shouldn't try
m user v because it's not in the nesting
i mean if
ruby was the one that was resolving that
constant
m wouldn't be checked and this one is
even more able
because indeed if if you give me a list
of modules
arbitrary i can give you a piece of code
that has that list of modules
as nesting arbitrary it's arbitrary
interesting you cannot
assume anything about nesting in this
case
you have module av and inside that
module will be
module mn which is nesting at this point
m
n and a b and active support has no
idea of this
you know it's not passed to the
transmission thing so you you cannot
you cannot know it so not only you
shouldn't be
checking m but in addition to not
checking m
you should check av if you were
emulating the algorithm but
you cannot you you don't need you don't
i mean
in all these examples if you put here an
unknown constant
the same module is triggered for con's
missing
but the rest of the thing is missing so
you don't know
and
that's that's uh even worse it could be
that your model in you know in the
generic thing if you are writing active
support you are
you know you have to deal with the
generic thing uh with all situations
that you can have in ruby files
one of the situations that the module
the cons missing thing is triggered on
could be anonymous
and there's a there's a the
there's a weird thing here the the eval
family of methods push
uh push
okay so next thing uh i didn't
cover this in the in the refresher but
nesting only changes with module
with the module keyword and with the
class keyword and with the
eval family of methods
if they are passed strings in particular
if you open
any block any kind of lock the nesting
is untouched
in particular if you say class eval
block the nesting is untaught the next
thing is it is very very lexical thing
so you if you look at the source code
you you see which modules are there
define it that's nasty
at that point it's in the source code
you can see that
and but there's an exception if you do
module eval or instance level or
classical
and you pass a string as an argument
then ruby one
evaluates that the string pushes the
other module in particular
it could be an anonymous module so this
is very very
it's case but could happen so in this
situation you don't have no idea
of what's
anything you don't even have a name for
the module
you don't you do not even have a name so
you don't have to
you don't have the nesting but even
there's no name so
you cannot assume anything so
uh these are trade-offs done by active
support
trade-off the name of the module that
gets the
the hook call it reflects the nesting
that's an assumption
it's known that it could be false but
you do that trade-off because you cannot
do anything else
you you can you cannot be smarter than
this
and so this is the assumption that you
are basically in this situation
and for anonymous modules you cannot do
anything so the
what active supports does it assumes
that the nesting is object that you are
you know
your lexical scope it's the top level
scope
so you have to do something that's what
it does
in anonymous modules but fortunately
thanks thanks to the fact that uh
blocks do not push nesting the only age
case that where this can happen
it's with a ball family that receives
strings as arguments
the other thing that you don't know it's
which is the algorithm that failed to
find the constant so
if the algorithm is the one for relative
constant names
like this one uh this
this thing is going to find one which is
a top level constant
why because it checks in m in m
is not defined let's assume that
ancestors there's no ancestors for them
then
it checks object so you find x right
so here this works but if you instead of
doing m
x this way you do it this way the
constant is not is not found
why because it checks in the table is
not in the table finish
and you know what this thing and this
thing is going to trigger the same call
you know in m that x was not found
and you know your name which is m but
you don't know the algorithm that
triggered this thing
so the trade-off here is something that
it's you know it's a partial solution
because there's no solution for this
so if active support receives
a constant and checks the you know
it goes up the nesting or at the assumed
nesting if it finds that custom defined
in some of the pattern modules then it
says hey this is going to be
uh this is going to be this case
because otherwise the hook wouldn't have
triggered in the first place
right but why is a partial solution
because
because it depends of of the constants
that are defined at that point of
execution
so it could be you know depending on the
load order or depends on
the code path uh you know execution
you know but it's the best you can do
so another thing that that you may
you may have noticed is that ancestors
are not fault
so active support does this backtracking
which is like following the nesting but
it does not attempt
to find the ancestors of the originating
module
and try to find directories for those
ancestors and start the game
right so the corollary of all this
is which is a you know a very important
key of this talk is that active support
does not pretend
to emulate the constant algorithm why
because it can't
so the thing is you have to to think
about this
in in the in a positive way which is
active support provides you
this feature which is if you use
constants this way
and you follow the conventions and and
and you know and and
write the files in the comm in the in
the following the conventions
then that that's the contract that's
what's going to work
if you expect that active support uh
solves any you know resolution of uh
constants in uh you know following the
generic rules of
ruby is not going to work but that's not
the contract you know
so uh there are these you know
essential limitations and that's the
contract
active support um offers
so let's go
with uh all right yeah i think i can i
can i can
finish the presentation so uh request
flow request flow
uh depends on on cache classes cache
classes you know
and it's the flag that says whether you
want your classes to be reload or not
which in development by default it's
true
uh so cache no so it's false and you
know in production
mode you don't have to go reload
and so for doing this in
it was it was simpler before but in 3-2
there has been some optimization there's
a thing called
file update checker that that it they
will given a
series of directories and file names
it's able to say
whether from the previous execution
something changes basically
so it has an api that says hey your set
of things has been updated
from the previous car it implements that
kind of thing
and then we have some uh okay some
hd configuration things that are not
generally very used but they exist which
is autoload one's path
you you are able to say to active
support hey
autoload these things but only once so
do not reload
and some people use it for instance to
out a lot from lip
some people like to auto lock from lip
but not but do not have
lip reload and they put lip in out a lot
one spot the only thing is that uh in a
very very
little use cases people want to actually
say hey
this constant i know it's not out a lot
but please
unload this constant for me because i am
developing some gem or something
and i am you know trying with an
application and i want my gem to be
reload
so that you can put in explicitly unlock
loadable constants uh this thing
and then in active support uh sorry not
result
in in the application and real time
there's this thing that says well
if you want to reload things we are
going to push a middleware
and this middleware uh looks for these
things
the routes the locales and the
application files
and it works this way if the if the
roots are changed
the roots are out load again
and the constants are gone so
the way this happens the way reloading
happens is that
the constants that were loaded
are removed from the constant tables of
three modules
so if root chains roots and classes are
reload if locales change they are
loaded and also are reloaded the classes
and finally
if ruby files a change or if
schema rv of a structure sql change
classes are going to be reload so
that's the thing if if the if the file
is the file uh
files change uh the constants are going
to be wiped
from the constant table of player
modules and
for doing that you just use you know the
the you you have
uh stored the constants that you
autoload you have the api to remove the
constants
you remove the constants by hand and
since you remove the constants in the
next request
uh when you are going to use the user
model the user constant
again is unknown why because the
constant is wiped
the user model the user class could be
stored somewhere else theoretically
so you are not cl you're not really
reloading the class the class could be
alive
somewhere else if you were stored which
is a bad practice but it could happen
theoretically what you remove is the
user constant
you if if the user constant if the user
class is stored somewhere else
what you cannot going to do is uh access
to that class
object using the user constant that's
not you're not going to be able to do
that
but the user class is independent of the
user constant could be a store somewhere
else but in any case you've removed the
use
the user constant so when you're going
to use the user constant again
next in the next request conjunction is
triggered again and that close group
and that's the presentation all right
all right do we have questions
can you change the name of the constant
or a module once it's assigned
or is it like blocked by the interpreter
yeah good question
so again let's let's do that let's do
the point
constants are just just storage just
storage and you have you happen to have
a constant table
in the module so since ruby allows you
to change a constant you could
you could you you get a warning but you
can
so in that sense storing a a class you
know
this thing like module m class c
this this c assignment inside inside the
constant table of m
is no different than doing c equals one
so you can change any of those but i'm
asking about
uh you have this uh
the the class object for example user
here's your class that you assign to the
to the user constant right and you then
uh
like execute the algorithm for removing
the the user class
from the table so then when you
when you for example start the user
class under under a variable if you do
the variable dot
name does it have the name of the user
and can you change the
the name the name no there's no api i
don't know whether
if you have c code you could do some
weird stuff but
let's say that way there's no api to
change that you cannot change the name
that's controlled by interpreter all
right thank you
yes
what would happen what would happen if
you said like class dot new do
like x equals self.name insi
as you're defining the class yeah so you
remember that i said
they are not exactly equivalent so the
when you do the assignment and the class
and the definition
with the class keyword they are
equivalent as for the repositories guy
but i said
there's not there's some details one of
these details is that
that if you if you say class c
and body definition when you are in the
body definition
the the the set the self at the top
level of the body which is the class
has the name define it because when when
when
the interpreter process process
processing
uh the class keyword at that point the
name was set
but that that that's a good observation
because if you say class new
block indeed at that point what this
that's one of the little differences
at that point the class has no name it's
an animal so if you say
self name uh uh at that point of the you
know
within the block effectively you get nil
i think it's kneeling one nine
this has changed the one in one of them
was empty string and the other one was
near any in any case
within the block the class is anonymous
and if you check the name it's anonymous
it's when you have done the assignment
that you get the name
and the assignment in that example in
this slide was like
immediately done but you could let you
could say
class new store that in a variable and
half hour pass
then you assign that variable to that to
some constant let's say c
it's at that point you get the name
right
yes here hi uh very short question
what presentations are you using sorry
yeah okay unrelated question but what
presentation software are you using here
so that's a really nasty and dirtiest
groovy script that i wrote for this
conference so it's
where do you find it all right all right
what no i wrote it
oh where do i find it so
okay give it okay
it's all right so
[Laughter]
i'm going to be ashamed
[Applause]
[Music]
okay i publish it anonymously
it looks very good okay thank you yeah
hi in release to
point x uh leap directory was in
autoload path
yes and in three it is not yes by
default you can always add it back
that's right and some people i add leap
directory to outlook pass and some
people
use required dependency to allow
to reload their classes
can you explain what which
way is better or how they differ
yeah i mean um
that was like a field of kind of a
philosophical
uh decision which was that
look lip it's kind of like bender
but it's closer to my application to my
company
or something like that and some people
in core
felt that lib did not belong to the
lead to the directories you should
autoload and
if for for in production mode
if you run
passenger with with ruby enterprise
edition
or if you are in in thread safe mode
uh since constant autoloading which is i
mean this topic is big uh there's
many things that i've left but some of
the topics which are interesting is that
constant autoloading
is not thread safe so since since it's
not thread safe
ruby ah sorry rails needs to
execute all your files in the autoload
files
in order to be able to to to
have control when you so
in production mode constant outlooking
happens but it doesn't happen on demand
so there's a in the boot process you go
and execute
everything constant of trolling
still happens because you could execute
user's controller dr v
and have a country constant in the top
level and
that comes to country constant if
country country rv
has not been low it's still going to
trigger some consequences so constantly
closing still happens
but uh that all that's all executed
in uh in boot time before you start to
do any threat or anything right so the
the thing is
there was a discussion internally should
we
execute everything in leap and the
answer was it doesn't look safe
you could have strange things in leap
like templates or stuff
that you don't you do not want to have
executed automatically by the framework
so that was like the decision to say
okay let's
let's keep leap out of this
you know automatic thing and and
you know and uh right so only go for abp
no which is the best practice it depends
it depends on your application and
in the end at the end of the day
something that that is your i mean some
people
like to have everything out a lot i do i
put
a leap in auto load and some people
don't
i don't know it depends on you so i my
answer is there's no best practice
so to do the thing that that you like
okay uh one last question
um so if you're a cool kid and you add
like services and presenters i'm right
there yeah okay
services and presenters and stuff like
that to your app
so you put them under app um
can you name space them so like you have
a sign sign-up service does it have to
be called
sign-up service or you can call it like
service column column sign-up
okay so you if you have app services
it acts uh as far as the things we've
seen it
exactly well that app controllers so you
can name space
uh so when when we said when we saw
those examples
when we we looked for partial paths
those partial parts are checked against
all
the directories in the autoload paths
in particular if you have abp services
among those directories
um so you you will get the namespace
resolve
so you can do both actually but what i
mean
your class and the app services can be
called
signup service or services column column
sign up that's right
all right thank you
all right thanks how sorry all right
okay thank you