Class Reloading in Ruby on Rails: The Whole Story

Ruby on Rails applications do not need to require the files that define their classes and modules. In development mode, code changes take effect without restarting the server. How's that possible? This talk explains how this works in depth.

You'll come out with a deep understanding of how constants work in Ruby, constant autoloading in Rails, how and why does it differ from Ruby's builtin algorithms, and how class reloading is implemented.

Xavier Noria is an everlasting student and father of the most wonderful girl. An independent Ruby on Rails consultant from Barcelona, Xavier is a member of the Ruby on Rails core team, Ruby Hero 2010, and proud author of Rails Contributors.

Help us caption & translate this video!

RailsConf 2014

00:00:01.760 [Music]
00:00:16.920 all right so um this is an example with a with a controller
00:00:23.680 and uh normally we we would need to put those two requires at the top right
00:00:30.640 because this controller is inheriting from application controller so in a you know normally in
00:00:36.280 a ruby Library standard Ruby Library you should need to require you know the file that defines that that that class and in
00:00:45.719 the index action we are using the post model so normally uh we should be requiring post
00:00:52.160 to have that uh you know Define it when the when the when the action
00:00:57.440 runs but you know that in ra actually you don't you do not need to do that
00:01:02.800 indeed this has a number of issues first it it look it looks like kind of
00:01:08.320 redundant right we have post and require post application controller our R mind
00:01:14.720 uh you know quickly says there's something you know redundant here we could maybe automate something or or or
00:01:20.520 something like that the other thing is that require requires the file only once
00:01:26.720 so if if if something changes uh is not going to be reflected memory you know
00:01:33.040 and in development we we like to be able to change things and and have them you know refreshed in memory
00:01:39.840 automatically so rails provides this this feature which is constant
00:01:45.479 autoloading and glass reloading and it's it's one of of my favorite um features
00:01:51.799 of of rubian rails first it's it's something that is uh focused on what I I
00:01:59.520 believe is the most important thing when you design software which is uh how do you use this this you know how do I use
00:02:06.479 rails this is very convenient for me as a as a programmer as a ra programmer you know to have this feature so this helps
00:02:13.360 a lot you know in your day-to-day it's a it's a key feature for me um the other thing is that it's kind of I don't know
00:02:20.080 it's kind of an assuming you know it's it's just there silently doing it its
00:02:25.760 work you know I don't know there's something there and also it's technically interesting I believe so
00:02:31.640 this is the talk is about how this works and it it has three sections the first
00:02:36.840 section is a section about constants in Ruby so that's going to be just Ruby and
00:02:42.480 that's because uh this topic is is a a topic specifically about constants and
00:02:48.120 and it's it's going to be good that we have them fresh in our minds how they work in
00:02:54.040 Ruby so first first section constants in Ruby second section is how
00:03:00.400 this works how this constant outo loading works I refer the post model and
00:03:07.040 it's just defin it so indeed the idea is that is as as if you had your
00:03:13.519 application already loaded you know you you don't not have to care about that this you can work more or less as if
00:03:19.200 that was true the third section is class
00:03:26.080 reloading because we have here two actually two features one one is that the the constant is outo loaded for you
00:03:32.799 and the other one related but different is that in addition to that in development mode uh by default the you
00:03:40.599 know if you change something that's refreshed memory that's that's a the thir section all right so let's go with
00:03:47.720 with the constant refresher you know what's a constant in Ruby we have here an assignment x uh we
00:03:54.840 we are assigning an integer to to the to the x constant uh in most programming
00:04:01.599 languages constants are a like a trivial topic there's not there's not a lot a lot to say about constants but
00:04:08.280 surprisingly in Ruby uh it's a it's a really I don't know there's a lot of of
00:04:13.840 of things to say about constant it's by far it's not by any means something you know uh as simple as in other
00:04:22.479 languages um here we have a a class definition it looks innocent but and
00:04:29.000 here here the point this is this is a a constant assignment indeed we don't we do not see it because we have the class
00:04:35.320 keyword and that that's working behind the seats but there's a constant assignment there
00:04:41.039 so in reality what happens is this so the the the we have here three I cannot
00:04:47.919 use the laser so I'm going to try to describe where where I am the the first thing is Class C we
00:04:54.960 defined the class C as in the in the previous Slide the second chunk is
00:05:00.039 equivalent equivalent as as far as conents is concerned then there's some stuff with a scope and some stuff that
00:05:07.039 doesn't matter for our for for this presentation but if you define a class
00:05:13.320 and assign that class to the C Conant that's the same thing the class keyword is doing the same thing I mean this is
00:05:20.319 I'm not talking about the implementation I'm talking about the conceptual model in Ruby it's it's that so there's when
00:05:27.080 we say the cclass we are doing an views of language because the class is the
00:05:32.199 object that it's stored in the C constant like you could store it in a in a variable you know so it's in a in the
00:05:39.880 C constant so Ruby has constants and has class of module objects and they are
00:05:46.120 independent you know uh things of the language when you define a class that
00:05:52.440 way uh there's a little coupling there and that's also in addition uh you know
00:05:59.960 give it to you in in know in a simple way with a class keyword you know but
00:06:05.199 once you get that definition they are constant and class object stored in a
00:06:10.319 constant the same way we stored a one in the x constant in the previous slide same way there's no difference you have
00:06:17.280 X storing one you have C storing a class object there's no
00:06:23.000 difference and here if you ask in the third in the
00:06:30.000 third um um chunk of code if we ask uh for the name of this class we get c as a
00:06:38.840 name and why let's suppose the first chunk does not exist right let's suppose
00:06:44.880 we have only the the second and the third CH uh chunk so the reason is that
00:06:50.680 when you assign to a constant The Interpreter says if the object I am
00:06:58.319 assigning is a class or module and it does not have a name it's Anonymous then
00:07:04.400 I am going to put the name according to the constant I am assigning the object
00:07:10.400 to that's what happens that's like you know the code in the The Interpreter that does this right so you get you get
00:07:19.360 c as a name and by the way this name this this this method call
00:07:26.280 is calling a method on the object that it's store in the C constant this is one
00:07:32.360 of the most important slides of the presentation so what happens in the third CH is that there's a a c constant
00:07:40.080 that is the same you can think of a variable to to separate clearly
00:07:45.360 constants and class and module objects there's a c con constant that evaluates
00:07:51.039 to a class object that responds to a name method that yields a result that's
00:07:56.479 what is happening there so when when The Interpreter boots you have a number of
00:08:02.639 constants already defined you know but they are constants they are not classes
00:08:08.599 so when when we say the a string class and we write it that way we are doing an
00:08:14.879 abuse of language it's a of course it's a convenient of of use of language you are not going to to say you know give me
00:08:21.840 the object that is stored in the string cant by default by interpret something like that which would be you know the whole thing but it's not it's not it's
00:08:28.599 not convenient but that's really what's happening we have a string constant that
00:08:34.800 stores a class object that is created by The Interpreter when you
00:08:41.399 would constants are stored in modules so
00:08:46.519 for instance this is the the um implementation of the module class in
00:08:51.920 rinus you see it has a constant table you can think of that as as a h
00:08:58.079 table it Maps the name name of the constants that that module
00:09:03.399 has with the value it's like it's like a has table it's like a like a symbol
00:09:08.800 table you know so they are starting modules and again this is not implementation this is the conceptual
00:09:14.200 model in Ruby constants belong to modules conceptually so here we are assigning
00:09:22.200 one to the constant X and what's happening
00:09:28.120 there the module and I am going to spell everything now that's not that's not how
00:09:35.880 you talk you know and you in your everyday programming but what happens
00:09:41.560 here is the we are assigning one to a
00:09:47.040 constant called it X that is store in the constant table of the
00:09:53.160 module that is stored at that time in the constant M we normally say
00:09:59.880 X is stored in M right but to to clarify everything
00:10:06.399 because one of the purposes you know one of the things that we are going to have clear when when we finish a talk is that
00:10:13.040 that this there they these things are totally deced so we are storing the X in
00:10:18.600 the module that is store within the M constant indeed the module could could
00:10:25.720 be call it something else and
00:10:31.959 again the class keyword and the module keyword are basically constant
00:10:37.720 assignments so this is something in the first Chun of code this is something that we do
00:10:44.800 routinely module something that creates an name space for you and you define a class in that Nam space all right that's
00:10:52.440 a constant assignment all class of module keywords are creating constants for you so it's equivalent to the second
00:11:00.959 Chun the second CH creates a a class
00:11:06.320 with with a Constructor class new assigns to SX
00:11:12.160 parser and then if you ask for the name of this of this class object it returns
00:11:18.920 XML colon colon SX parer why because it it is
00:11:26.519 storing the class object in a constant that belongs to a module call it XML
00:11:33.079 then The Interpreter builds this XML colum colum thing for you okay depending
00:11:38.880 on the on the name of the module you are defining this
00:11:46.560 thing and this is another very important slide of this
00:11:52.560 presentation because we are totally going to decouple constants and modules here we have something Sim similar to
00:12:00.120 what we had before but we are going to stress that the module and the constant are different things so in the first
00:12:08.560 Chun we Define a module XML empty all right
00:12:14.320 then we do an assignment this assignment it's it's
00:12:20.440 very important in uh if you want um XML evaluates to a module object that we
00:12:28.800 assign to another constant same thing as if as if XML contained on string or
00:12:35.040 something more ordinary you know there's no difference it's just an object that is stor in the constant we assign that
00:12:41.160 object to uh in this case the N the the M constant all right so after this uh
00:12:49.480 line the M constant and and the XML constant hold the same
00:12:57.360 object if then we reopen the M module because in the in
00:13:04.839 the in the third Chun we have module M what does module m means so The
00:13:10.120 Interpreter says okay M do you have an object with this constant
00:13:16.199 exists yes it has a module all right so since it has a module is going to reopen
00:13:22.199 the module it doesn't matter that it was call it or assign it initially to the
00:13:28.000 XML constant it doesn't matter that the name of the module is XML doesn't matter
00:13:33.079 it's a constant evaluates to a module we are going to reopen the module and if we
00:13:38.800 Define the SX paral class inside that name
00:13:44.560 space the name is still going to reflect the name of the
00:13:50.680 module under which we are going to Define this constant you see the separation so the XML ends in the name
00:13:58.320 of the class because it doesn't matter which is the constant that you syntactically see in
00:14:03.759 the scope what matters is the module stored in that constant of course this is something that that we do not uh do
00:14:11.680 you know in our everyday programming but if we understand this example we we we are able to distinguish and and know
00:14:18.759 what's going on you know since modules store constants we
00:14:27.360 have an API to modify by the constant tables of those modules and that's this
00:14:32.759 API that you maybe know cons get con Set uh cons defined Etc so that's like a
00:14:39.800 high GPI get get me this constant from this module do you have this constant you
00:14:47.560 know all right
00:14:52.959 so to in order to resolve constant names Ruby has three algorithms
00:15:01.079 we are going to see the three of them uh from the easiest one to the more complicated
00:15:06.680 one this is one is here and it's kind of implicit we maybe not realize there's uh
00:15:13.199 there's a constant lookup here so we have a
00:15:18.639 module admin and a users's controller uh that we want to Def uh
00:15:26.360 Define uh within the me Nam space or an in nam
00:15:32.759 space What Happens here remember that every time you use the class or module keyword The Interpreter checks whether
00:15:40.240 you are defining something or reopening something so there's a check going on you
00:15:48.040 know Ruby needs to check whether uh user's controller is defin it in ad in
00:15:54.880 in admin module I don't remember where goes the accent admin or admin where goes
00:16:01.920 admin admin okay thank you so in the admin module and it's only going to check the
00:16:09.519 admin module exclusively even if if it has ancestors it doesn't matter it's going to check
00:16:15.680 the admin module which is what the name space we have in the scope so if you the constant users
00:16:23.519 controller exists in the admin module is going to to check if it's a a class and
00:16:32.399 I don't know and reopen the class if it's a class otherwise it's going to work all right and this is very important it's
00:16:39.079 only going to check the admin module so if you have a users controller already
00:16:44.639 Define it in the top level scope is it it it doesn't going to to
00:16:49.880 matter it's not going to you know to reopen that top level thing it's a
00:16:55.440 strictly the module I have in a scope all right by the way in the top level constants
00:17:02.600 are stored in in in in the object
00:17:09.760 right okay the second one to to explain the second one we need to to revise the
00:17:16.600 concept of ancestors of a module or or class okay let's go through this a slide
00:17:23.720 in the first Chun we Define an end module in the second Chun we Define an M
00:17:29.480 module that includes n then n becomes an ancestor of M all
00:17:35.919 right then we have class D and finally Class C inherits from d and includes M
00:17:44.200 so we have a little bit of everything to to say to to see ancestors in all their
00:17:50.480 generality you know so which are the ancestors of
00:17:55.799 C the you see you see at the bottom the ancestors of C so first C so technically
00:18:02.400 the ancestors method Returns the receiver and in the present in in this
00:18:07.520 in this presentation I am going to refer sometimes to the ancestors I am I am going not to include the receiver in
00:18:15.080 that in that in that notion you know um ancestors uh uh from me up you know but
00:18:22.880 the ancestors method Returns the re all right then M then n because n is an ancestor of M
00:18:32.000 you know so it's kind of recursively you know unnesting everything for you until
00:18:37.520 it gets flat that's what is is doing then once you have you know
00:18:45.240 recursively unnested everything regarding modules including modules uh
00:18:50.840 then it goes the super class and finally if you we have the
00:18:56.320 rest of ancestors you know object kernel and finally basic object in in resent
00:19:03.360 rubies so these are the ancestors of of a class of module and this is the
00:19:09.520 algorithm that is used to resolve this uh this uh particular case and we are
00:19:15.200 talking about the X so in this particular thing we have two constants M
00:19:23.039 and then the X the first m is not related to this algorithm we are
00:19:29.280 explaining now let's suppose let's suppose that m is resolved somehow and
00:19:34.360 gives you for instance a module okay so this slide is about how the x is
00:19:41.120 resolved and the way the x is resolved is checking M do you have the m in your
00:19:47.600 constants table uh let's suppose the answer is is no then is going to go through the
00:19:54.440 ancestors of the M module okay checking one by one if you
00:20:00.159 find the constant is going to return a value otherwise it's going to exhaust
00:20:05.720 the ancestors and is going to call a special method called it cons missing
00:20:10.919 cons missing is is similar to Method missing like if if if you were asking
00:20:16.919 for a constant and it was not found you know in the places that that uh uh
00:20:22.679 there's a look up for um that method is going to be called and uh Ruby has uh
00:20:29.559 cons missing defin it in module and that's that's the method that raises an name error if the constant is not found
00:20:37.440 it's a it's a method indeed which is racing with that you know error Mage
00:20:42.840 that say that the constant didn't exist so only checking the
00:20:48.039 ancestors and C missing if if it fails and now we go to the most complicated of
00:20:54.240 the three and also maybe the most uh common one
00:20:59.440 to use which is in this situation uh H we we are going to introduce the concept of nesting here
00:21:06.799 also which is important for the third algorithm so um we saw the ancestors we
00:21:14.440 are going now to see um the nesting and both of them are take it in taking uh
00:21:20.880 take it into account in the third algorithm so the idea of nesting is that
00:21:27.080 nesting reflects the the nested name spaces you have at the point of execution that that's the idea all right
00:21:35.200 so in this case we have m n c okay and if these constants store the
00:21:43.640 modules that we normally have in those constants where the name is match we are going to to have in module
00:21:51.559 nesting which is a method that tells you the next thing at at a given point uh those those three things okay the cclass
00:21:58.640 it's m MNC the MN module and the M module you know that's the next thing so
00:22:04.400 it's it's something syntactical you see the source code you see the nesting okay it's syntactical all
00:22:10.039 right at the top level the nesting it's empty and it's important to say that the
00:22:16.279 nesting is only Changed by the module class uh sorry the module U keyword the
00:22:21.840 class keyword and then the IAL family let's say family there are several
00:22:28.760 methods or several or eval like methods uh when they take a string of code to
00:22:35.080 evaluate not when they check a block but when they take a string then the nesting is changed for the con context of the
00:22:41.919 pollution of the execution of that string but that that's the that's the
00:22:47.279 only thing that changes the nesting in particular class eval and these kind of
00:22:52.360 things when they take a block the nesting is not changed and this is important for the resolution uh of
00:22:59.279 constants with relative names which is what we are going to do now so you see in the third CH of
00:23:05.159 code uh module nesting it has not changed still it's empty even if for
00:23:11.919 some other stuff is the m and C class that is in a scope to Define methods and
00:23:18.159 you know for other things that class is in a scope but the N thing is not is not
00:23:23.559 uh that that class is not pushed to the to the nesting all right
00:23:30.520 so what happens with this X in the middle of the screen the algorithm goes this
00:23:38.400 way it checks whether X belongs to the the class stored in the C
00:23:45.200 constant let's suppose it doesn't exist there it is going to go up to the next
00:23:53.240 up following the nesting so it's going first check C then well the name is m m
00:23:58.840 and C but let's see let's say it simple C then the next module
00:24:04.640 MN then the next module M let's suppose it it has not found the constant in any
00:24:10.559 of these three things then is going to follow the ancestor chain of the cclass m and C
00:24:22.720 Class okay and then there's a special rule here
00:24:29.960 um with this with the cclass we are done if we if a constant is not found it's going to is going to call cons missing
00:24:37.120 but if the if the name space in a scope the most nested you know thing in in the
00:24:42.799 in the in the nesting uh it's a module in instead of a class
00:24:48.039 then uh The Interpreter manually checks
00:24:53.360 object object does not belong to the to the nesting Okay so in in the first
00:24:59.320 thing when when when we we go up this way it say C and M and stop there we are
00:25:08.440 going now to to go through the ancestors of c and we have not checked object yet
00:25:14.120 object is the last resort so if the most netive thing is a module then there's a there's a there's
00:25:20.919 a you know an exception in the in the in the algorithm um a special rule that says we are going to check no object
00:25:30.960 all right if it f if it fails it involves cons
00:25:37.440 missing to simplify the the the this these uh descriptions of the algorithms
00:25:44.200 um um I skied this little detail but we know uh are going to see it you you know
00:25:50.480 this uh Kel Auto thing kernel
00:25:55.600 autoload um allows you to Define here um a constant sax par let's say and uh
00:26:04.080 associate that with a with a file with a file
00:26:09.120 name what that does is basically the idea is to lazily load
00:26:16.080 the constant when you need it so when you need it means anytime you try to do
00:26:23.880 something with that with a constant geta value ask if it's defined something like that
00:26:29.640 transparently the The Interpreter if you ask if you are asking for that constant
00:26:35.120 is going to to check if there's an autolot and if there's an autolot is going to fetch the file and if the file
00:26:41.440 defines the constant that we are expecting is going to return the value it holds okay so every in in every every
00:26:49.080 single time I said it checks this module it checks the ancestor it checks that check is always a check if there's defin
00:26:55.919 it and if there's an autol go an AOL all right that's the entire the entire
00:27:03.360 algorithm this is very important I I I've been asking ask it a few times this
00:27:09.039 U the way constant autoloading Works in Ruby and in rails sorry uh is not based
00:27:14.120 in in in in this autolot mechanism is it's a different uh uh thing the
00:27:20.000 implementation we are going to see it has nothing to do with with uh with this AOL feature and the problem is that is
00:27:29.279 it's it's just not not possible uh there are there are a few things with with this autolot thing first thing is that
00:27:37.480 it only it it only accepts constant names you cannot pass constant paths all
00:27:44.039 right so that that uh introduces some stuff for some difficulties to support
00:27:50.039 name spaces in rails the other thing is that it does a
00:27:56.480 require and you know in order to be able to out to reload things we we need to be
00:28:02.440 able to exe to execute files when they change so if you use require um uh you
00:28:10.559 are not going to be able to trigger this again you know and in addition you you could you could
00:28:18.000 decorate maybe I don't know as a hack ker require but in addition to that at
00:28:24.240 least in in MRI that requir is a particular required in see that is not kind required it it uses a particular
00:28:32.080 required requir all right still you can do a hack with that
00:28:39.039 because how does require know if something was loaded so there's you know there's an
00:28:46.039 array call it dollar double quote that has the names of the files that that has
00:28:52.919 been loaded so far require checks whether whether the file you want to load is there and if it's there uh it
00:28:59.840 does nothing if it's not require and stores de you know so that array is
00:29:06.159 mutable so if we remove the string from the array require is going to be foed
00:29:11.360 and it's going to load again the file okay but it's not it's not yet enough
00:29:18.880 even if we did that hack we had the we we had the the issues with name spaces there's no there's no API to remove an
00:29:27.000 autoload for instance so so if you remove a file that defines the user class or something we would expect that
00:29:34.000 to I don't know to not work there should be no autolot for user you know but you you cannot remove autolot that you
00:29:40.279 already have defined so there there's a number of reasons um that that prevents
00:29:46.679 prevents rails from implementing out loading with this thing and it's a b because it could be so transparent it
00:29:53.000 could be so smooth I don't know it for me it could be the ideal solution for
00:29:58.120 constant autoloading but um I don't think it's possible to implement it with
00:30:03.200 with this feature of Ruby okay so we are ready to go uh for
00:30:08.399 constant outo loading the thing
00:30:14.000 is we are going to to um autoload the user constant you
00:30:20.960 know in the we are we we have been invoked the action up to that point in the in the execution of the code the
00:30:27.519 user model was not defined and what happens Ruby says hey
00:30:33.000 you are accessing a user constant I don't know anything about that constant it looks for the constant
00:30:39.600 in users controller is not there admin is not there ancestor is not there and
00:30:46.720 what happens it calls cons missing you know and rails defines a
00:30:53.039 custom cons missing that's that that's the key of this of this feature that cons missing
00:30:59.159 so instead of the default cons missing that just raises we have a uh uh so cons
00:31:04.559 missing is a method and the cons cons missing cons missing is called it doing a method dispatch ordinary method
00:31:10.960 dispatch if you in the ancestry you have defined you know something in between that one is the one is going to be
00:31:17.440 invoked so cons missing uh gets the
00:31:23.360 constant name you are looking for in this case uh the constant name would be be uh
00:31:29.840 user and it's uh it's running in the context you know of the um admin users
00:31:39.200 controller um class and that's the information you have you know it was invoked in in admin user controller the
00:31:46.720 name we are looking for is user those are the two bits of input we
00:31:53.279 have there's a this this configuration um collection in in in ra application
00:31:59.720 that by default it has everything under the app directory directory and it's
00:32:05.200 it's mutable you can you can add stuff uh um in that collection that's a
00:32:11.120 collection of of directories to look for um um constants in autoloading so it
00:32:18.240 goes this way first it checks whether there's a user
00:32:24.279 RB uh below um ad user controller so is
00:32:30.840 is that file do do that file exist Pro probably there's not even a
00:32:35.880 users control directory you know but you check this this path exists in the file system let's suppose the answer is
00:32:43.960 no next step and this this is this is a strange but we are going to see uh in a
00:32:51.200 minute what it means but let me let me tell you that it checks also whether there's a user directory below the user
00:32:58.399 control directory okay let's suppose it doesn't exist then it goes one level up and we
00:33:05.120 are here kind of emulating going the the the the nesting up so the nesting here
00:33:13.880 is first admin users controller then
00:33:19.159 admin okay so we are kind of checking like more or less like Ruby do it's
00:33:25.279 different but it's more or less the idea you know this this thing exist here no Next Level
00:33:31.519 exist here that's why it checks whether there's an admin user RB let's suppose
00:33:38.559 the answer is no and also checks whether there's uh um directory directory admin
00:33:45.120 user and if all of these checks fail uh if we have a user RB in you know at the
00:33:52.760 top level is going to load that one and that's that's the way a user is loaded
00:33:58.919 okay and in developed mode this is this is done with load you know Ruby has
00:34:03.960 require it has load require requires only once load uh loads every time you
00:34:10.240 you want to load a file so in development mode is done with
00:34:15.359 load and in um production mode uh it's done with require by
00:34:23.040 default the thing with directories is that maybe you have have noticed that
00:34:29.560 when you have name spaces in a ra application you do not need to Define uh
00:34:37.119 um a file that defines by itself the module that you are using in the
00:34:42.760 namespace if it's a module so here's an example let's say we
00:34:49.159 have we have uh um some workers and let's say that for organ organizational
00:34:56.399 purposes in our application we have the workers in a workers directory it's plural or singular singular worker
00:35:04.800 directory okay worker directory something you know files uh maybe you maybe you have
00:35:10.800 noticed that you do not need to define a worker. RV file that defines the the
00:35:17.359 worker module you don't not need to do that you can do it but it's not required so the thing
00:35:26.440 is if is going to find you know doing this backtracking is going to eventually
00:35:33.200 find the work directory and in that case it builds an anonymous modu for you well
00:35:39.520 Anonymous first and then okay let's explain this it's going to we we're
00:35:44.760 going to match it with with the with the previous section so we store a worker
00:35:51.280 constant in object and assign uh a module to that
00:35:56.640 constant and this is a constant assignment it's a little bit convuluted it goes through the API but it's a
00:36:01.960 constant assignment so that module that it's Anonymous is going to get the name
00:36:09.319 of the constant we assigned to it Ruby is going to do that for us so when you
00:36:14.960 when you ask for the name of the worker module is going to say worker okay so rails uh does that for
00:36:25.240 you there are a few cases few I don't know coordinate cases where you need so
00:36:34.079 this thing is is lazy right and that's and that's fine that's good because you are not evaluating files until until you
00:36:41.079 need it you need them but there are a few few cases where you you need to be
00:36:48.079 sure that the constant is defined by the by the time uh but at some point in the
00:36:53.920 code and you can do that with required dependency require basically says load
00:36:59.760 that file now so I will so the constants are going to be defined now but do it it
00:37:05.760 in a way that is integrated with all the system and they are going to be reloaded and everything you know um um you we
00:37:13.720 don't not have time to to explain use cases for this for this but let me say that you need this rarely so this is
00:37:21.560 this is something exceptional do not take it like normal you know normal API that you use every day no no no it's it
00:37:27.560 only for some particular cases where you need to be sure that something is loaded
00:37:32.760 at that time so we keep we keep track of fully qualified staff and file
00:37:40.599 names um Kel Auto uh Kel load and Kent require are rapid because if the user if
00:37:47.640 the user uh uh if userb requires no ciri for instance dependencies has to be able
00:37:55.920 to know that user B was something autoloaded but noiri was something not
00:38:02.400 autoloaded he needs to distinguish them because it needs to know what was autoloaded and what was not because of
00:38:09.400 course interpreter has tons of constants you know it's important to to realize that
00:38:17.440 constant autoloading in rails is different it uses different mechanisms that that the Ruby the Ruby uh
00:38:25.119 algorithms first cons missing does not have the nesting we have the name of the class we
00:38:31.839 have the constant but we do not need in in which of these situations we
00:38:37.640 are because the nesting depends on the modules stored in the constants not in the constant names so the first the
00:38:45.240 first Chun of code is the regular one but the in the middle the nesting only has one module
00:38:51.720 MN okay so rails is not cons is not able to to
00:38:58.560 say whether the which is the next thing we we I know my name is
00:39:03.640 MN but MN is the name in the first CH and in the second CH and there's no way
00:39:09.240 to tell which of the both cases you are you know and we this is like very very
00:39:16.200 decoupled I mean you can build an nesting with any number of of of uh of
00:39:22.960 with any modules so generally speaking The Nest thing does not reflect the name space
00:39:28.119 it has nothing to do with the names of the things of course you normally do work with code that reflects it but
00:39:33.839 technically it doesn't need to reflect anything you the next next thing can be arbitrary as the third Chun uh
00:39:43.160 exemplifies and well there are even uh more Corner cases but we are ring a a
00:39:50.240 lot a bit um late so I'm going to skip this one so there's a tradeoff there's
00:39:58.640 tradeoff rails is going to assume that the name space you know the name of the
00:40:04.839 class reflects the next thing it's going to assume that if the code is not that way it's not going to play by the rules
00:40:11.240 of dependencies RV that that's the idea so it's better it flows better if if if
00:40:17.280 your if you name spaces reflect the name of the things
00:40:22.800 okay so this is the assumption that we are in this situation all right ra
00:40:28.359 rather than doing class admin colum colon users controller you can do that
00:40:34.040 it mostly works but it doesn't flow naturally with
00:40:39.240 depv let's forget about this which is a a corner case the other the other key
00:40:45.119 key information we we do not have is which is the name of which is the the
00:40:50.280 algorithm that was being used to load the constant we have no
00:40:55.680 idea we don't know so um here we do something that I don't
00:41:04.680 like very much I don't think this this is an elegant solution but it's the best you can do you cannot do anything else
00:41:11.560 we we are going to check whether uh the okay we do a check that
00:41:17.359 says if this if this check succeeds uh we we we kind of know which
00:41:24.280 is the algorithm but that check depends on the order of loading of the stuff which are the constant that that are
00:41:30.400 defined at that point I don't like it very
00:41:37.800 much uh third important uh difference uh we didn't mention any ancestors we only
00:41:44.640 did like the the directory thing okay which is kind of following the N thing
00:41:50.839 but we didn't say anything about ancestors and that's just because uh we
00:41:55.960 we have seen no use case for doing that and complicating things so uh it doesn't
00:42:01.240 do it so this is a corollary of of this part uh uh it doesn't emulate the way
00:42:10.040 Ruby actually does things because we cannot the the key information is
00:42:16.160 lacking we don't not have it okay so quickly the request flow you
00:42:22.440 know there's a flag that says whether you want to reload things outlo things uh there's something that monitors
00:42:28.720 whether files uh change and there's a middle where if if you want to reload
00:42:34.920 stuff that is going Toad the stuff um some stuff is watch it if you
00:42:40.520 Chang The Roots the Roots sorry uh these changes um locals and
00:42:46.640 everything and that's that's the that's the key point if something changes in development mode in the file
00:42:53.480 system then the constants we know because we were you know we we were
00:42:59.119 keeping track of the constants that we autoloaded those constants we just remove them rails removes those
00:43:06.720 constants like using the API remove cons remove cons remove cons remove cons that's done in the middleware
00:43:13.599 before the the when we start doing the next request and we detect that something changed so all constants all autoload
00:43:21.920 constants are removed so
00:43:29.720 the way reloading works is this is the following if we change it a file and the
00:43:36.599 constants are removed and we are in a request to that uh admin uses controller
00:43:43.119 what's going to happen that when The Interpreter arrives to the line with
00:43:48.280 that uses the user constant says it doesn't exist like it like like it said
00:43:54.359 you know in the previous request or whatever you know it doesn't exist then therefore I'm going to go through
00:44:00.640 through through these algorithms I'm going to try to load it and you get a new class object assigned to this
00:44:08.720 constant that we just removed it could be that the original
00:44:14.480 you know technically the original class object maybe you know it could be floating somewhere but it's not
00:44:20.000 reachable through the constant anymore in that if if your if your
00:44:25.440 application you know is is correctly um um written uh there should be no nothing
00:44:32.760 referen you know dangling uh um you know um in the in memory but they are
00:44:39.960 decoupled it could be it could still be that the class object uh were some um
00:44:45.319 somewhere living and I've seen projects that had issues because uh some stuff
00:44:50.839 like this they outed constantly in inal iers or in places that get not reloaded
00:44:56.640 that kind of okay anyway that's it all right thank [Applause]
00:45:06.250 [Music]
00:45:25.720 you