List

Zeitwerk: A new code loader

RailsConf 2019 - Zeitwerk: A new code loader by Xavier Noria
_______________________________________________________________________________________________
Cloud 66 - Pain Free Rails Deployments
Cloud 66 for Rails acts like your in-house DevOps team to build, deploy and maintain your Rails applications on any cloud or server.

Get $100 Cloud 66 Free Credits with the code: RailsConf-19
($100 Cloud 66 Free Credits, for the new user only, valid till 31st December 2019)

Link to the website: https://cloud66.com/rails?utm_source=-&utm_medium=-&utm_campaign=RailsConf19
Link to sign up: https://app.cloud66.com/users/sign_in?utm_source=-&utm_medium=-&utm_campaign=RailsConf19
_______________________________________________________________________________________________
In this talk we'll introduce Zeitwerk, the new code loader for gems and apps that is going to be the default in Rails 6.

We'll cover what motivated me to work on it, which are the issues in Rails autoloading and why is it fundamentally limited, usage by gems, and interesting aspects of the implementation.

RailsConf 2019

00:00:03.280 [Applause] [Music]
00:00:21.890 so this is the menu that we have before lunch we are going to introduce what is
00:00:27.509 a dive work the motivation that I had to work on this then we are going to see
00:00:34.559 how rails auto loads or has auto load that since the beginning to compare that
00:00:39.660 with a new solution and how is that integrated in rail six because this is going to be the new auto loader by
00:00:45.540 default in rail six all right so what is
00:00:50.610 divert it is a gem that provides Auto loading eager loading reloading of code
00:00:59.489 and very important it has no dependencies so Ruby is enough to solve
00:01:06.630 to solve these problems and very important as well it has been designed to work with any Ruby project so you
00:01:15.000 might have heard of of it may be related to rail six but it is an independent gem
00:01:21.149 it has been designed to be able to work with any Ruby project in particular gems your own private projects and it can be
00:01:29.819 used by other one free Wars so it's totally generic in that sense all right okay let's see first how do we use this
00:01:38.009 thing and after that we are going to get a little bit more deeper so the premise
00:01:43.739 to work with a jailbreak is that you have a project structure were file names
00:01:49.020 match constant paths that's standard in rails okay so it's like a very
00:01:56.250 conventional project structure I would say so for instance if we have user data
00:02:02.459 beam that should define the user constant right user underscore profile should define user profile and if you
00:02:10.860 have HTML parser the default constant
00:02:16.440 name expected from that file would be HTML parser with lowercase in in the in
00:02:21.750 those three letters but if you prefer to have HTML like like like an acronym you
00:02:27.780 can define there's a way to do that okay you can define a custom in flat or
00:02:33.350 your loader that says a everything by default i delegated to super or whatever
00:02:40.280 you know but in the case of HTML please do HTML in uppercase there's a
00:02:45.290 uninflected that is super super simple and deterministic different gems of
00:02:51.980 different loaders have independent in factors there's no way that one can interfere with the other one they are
00:02:58.330 deterministic and you have control about the way the files in your project are going to be inflated then also very
00:03:07.370 conventional namespaces correspond to directories right so in this case for instance we have let's say a hotel class
00:03:14.630 in hotel Hotel B and then we have module within Hotel class where we have
00:03:20.270 organized everything related to pricing ok so just you just have a hotel
00:03:26.960 directory and called hotel slice pricing this going as expected to define Hotel :
00:03:34.430 : pricing all right I call this explicit namespaces because
00:03:39.890 we have also support for implicit namespaces which is something that rails has had since the beginning which is
00:03:46.880 that if you are using directory just as
00:03:52.160 an image space for instance here admin role but admin is not a module with with
00:03:58.910 the stuff in it ok it's just playing the role of a namespace you do not need to
00:04:05.060 define admin dot RB ok defining module admin end ok you do not need to that you
00:04:11.750 do not need to do that in rails and you are not going to need to do that also if using driver
00:04:17.720 alright so basic usage is is very simple you just instantly the loader you say
00:04:25.040 which are the root directories of your project like in rails that is going to
00:04:30.230 be the auto load paths and a ruby gem is going to be lip and that's it and then
00:04:36.080 you call set up and on that you are ready to do anything in the case of gems
00:04:42.130 since there is a comma but for gems and projects that
00:04:48.210 technically are not gems you do not need a gem spec but that they have the una' structure similar to gems so this is
00:04:55.710 just a shortcut to push leap as the only root directory of the project which is
00:05:02.430 very common right and then also in gems person totally by convention is a
00:05:09.750 constant where all the letters are in uppercase so this this thing gives you
00:05:16.080 also an inflected that has this is that a special rule for Bastion Derby but it's just a shortcut so it is documented
00:05:22.169 and you can you do not need to use this in a gem if you have alternate you can just distant it standard I mean you
00:05:31.500 should use the previous API and that's it all right eager loading is this thing and the
00:05:39.780 first thing the first the first call is an is an instance method is showing an instance method the second one is
00:05:45.509 interesting it is a class method in zypher closer the says eager load all so
00:05:50.880 the point of this one is direc keeps a registry of all the loaders that have
00:05:57.990 been instantly read okay so in a web service like in a rails application a
00:06:04.650 demon of you or whatever you know oftentimes is convenient in production to load as much code as possible
00:06:11.580 on boot okay so if you are in a rails application and there are ten gems in
00:06:17.969 your dependencies that are using Deibert raise is going so rails calls this
00:06:25.020 method okay so to give you a concrete example and not only is your your rails
00:06:32.250 application going to be eager loaded but all the projects that are managed by Seibert they independent loaders are
00:06:39.900 going to eager load all of them alright so you get all of that all the benefit
00:06:45.659 in the main process indeed even you can even have your rails application not
00:06:51.120 using entire because you can still use the classical closer with rail six if you want but even if the
00:06:58.389 the application itself is not using desire but the integration that we have written in Braille six is going to call
00:07:05.800 this method in case you have dependencies that are using divert all right by the way
00:07:10.810 in rail six none of these api you don't need to use this API because the in ray
00:07:17.949 six is an integration that uses that that uses this api for you so your
00:07:23.289 interface in rail six is still config dot auto long paths config cache classes
00:07:30.819 that's the same interface that do you were using to tweak these things is the
00:07:36.099 one that you're going to use and is the integration is the one responsible for converting those standard parameters in
00:07:43.120 rails to the api of time right in order
00:07:48.909 to reload you have to opt in okay and this has two purposes one is to acknowledge at the API level that
00:07:57.150 reloading indeed is one of several possible use cases for this gem so in
00:08:05.139 general and a gem that is just a regular library does not need to reload right
00:08:10.469 because you have a gem and when you change something you may be rendered a suite but you do not have any service
00:08:16.779 running okay so in many use cases that I are at least I envision for the future
00:08:22.440 reloading is is not going to be used you are going to auto load or eagle load in
00:08:27.969 the indulgence but reloading is is something that is going to be useful for
00:08:34.240 things that that are running like web applications so by acknowledging this we
00:08:41.829 are able to be also more performant for the default case which is not reloading because reloading needs to keep some
00:08:48.970 metadata no big deal but so many data that we can save so for the majority of use cases that we save
00:08:55.420 that okay and if you are in a web framework and know that this is in
00:09:00.730 addition normally used only on DB Lohmann so the the combination is I am
00:09:06.610 developing a service in development mount okay for the rest of the motor I'm not going to reload either so
00:09:12.310 if you if you see it in that perspective it's just it's that corner case maybe
00:09:17.410 from the API reloading so that reflects that okay all right why did I work on
00:09:25.360 that so three things I just my first my initial motivation was the third one so
00:09:31.360 the result or other has some gorgeous it has worked very well for many years and it has been very helpful but there are
00:09:38.560 some gotchas that are intrinsic to the technique that it uses and I wanted to
00:09:44.529 to improve that in some in some way then
00:09:50.529 I started to work on this and I realized that I could also target to pain points
00:09:57.730 of mine a list to personal pain points which are that requires in in in in
00:10:03.460 arbitrary Ruby projects typically a brittle and a sense of of lack of
00:10:10.000 dryness that I have sometimes so for instance my project normally follow these conventions okay so if I have to
00:10:17.830 use the the user class I have to require user and for hotel it has to require
00:10:23.980 hotel I am I have a personal sense that I'm repeating myself all the time I am using
00:10:29.950 the constant and then just lowercase everything in require all right I am duplicating all this information if we
00:10:36.760 had like a good convention maybe we could automate this so that's a personal
00:10:41.890 feeling for the people writing requires it's fine perfect you know but this was
00:10:47.680 a pain point of me I wanted to work on that so why requires brittle I am sure
00:10:54.520 you have found this in any Ruby project except maybe a trivial problem project
00:10:59.890 but in any Ruby project is very easy to to forget requires so for instance we
00:11:05.380 have here an example class airplane that includes locatable that is not going to
00:11:11.050 fly because name error I don't know this constant okay so you
00:11:19.000 have to put a require for that to work but the problem is that requires have
00:11:24.749 our global effects as you know okay and the consequence of that I'm sure you
00:11:30.959 have faced this before is that you could have the original source code without the require and this could work this
00:11:37.979 could work because if in the cold path someone else required that file look out
00:11:43.379 a locket wall then when you arrived here since the constant of the module is you
00:11:50.009 know in the in the state of the of the process of the interpreter the interpreter knows that modulus is
00:11:55.259 already loaded so it works and the problem is that when you hit a different code path maybe in production
00:12:01.589 then you get an exception so i'm i I've
00:12:07.799 spent a few I feel a good deal of hours in the race codebase sometimes grabbing
00:12:12.959 and looking for missing requires okay so yeah I don't know I just I just it this
00:12:20.489 is Britain I just prefer not to do this if possible so divert all right
00:12:29.549 this is nano C which is a static site generator nano see instead of doing like
00:12:37.799 like cherry-picking requires it did something that that sometimes Ruby
00:12:43.259 projects also do which is in in the in the entry point of the gem it has all
00:12:48.659 these lists of requires okay this is this is conceptually like eager loading or correct so this also has a cost it
00:13:00.720 has a cost because every time you add a file to the project you have to remember
00:13:05.939 to go here and add the file to this to this list also this list has to be kept
00:13:12.059 order it and you may depending on real factors or something like that you may need to reorder this because because if
00:13:20.099 you have constants at the top level or class level they are going to you want
00:13:25.859 to be able to resolve them when the file is eager loaded so they have to be eager loaded before so you have to maintain
00:13:32.220 this by hand okay so nano see is no using driver every it's always delete okay so this was all
00:13:41.470 delete it calls he got load done so
00:13:46.720 that's that's the point you can streamline your programming knowing that your classes and volumes are just available everywhere that's it
00:13:53.440 you know forget about requires if you want so no we are going to see how rails
00:14:00.160 out to loads and and for for and to understand that and when the sender limitations of the technique of rails we
00:14:06.940 are going to just to do a quick constant refresher to have the the concepts you know just fresh in mind and be able to
00:14:15.480 to follow with the slides so you know constants trivial topic in many
00:14:21.760 programming languages like we are here we are here doing a constant assignment but in Ruby they are a very rich topic
00:14:29.440 with a lot of edge cases and stuff and the main reason is that Ruby does not have syntax for classes and modules so
00:14:36.340 when we do this we are doing a class as a constant assignment so we think in our
00:14:42.040 day to day we think in terms of when we see does that capital C with we think in terms of classes alright but in reality
00:14:49.090 technically that's a constant that's a constant so that's the same thing as doing this you you do instant it a class
00:14:56.050 object that is a store in the C constant so constants are storage like variables
00:15:04.330 they are stories they are like like this like dicks X storing a one there's no
00:15:11.020 difference this C is storing a class object this guy is storing an integer object this one is turning a class
00:15:18.730 object that's it and from here on constants and class and module objects
00:15:24.160 are independent you can remove this constant you can store the class object in a variable
00:15:29.350 they are absolutely orthogonal and that's what makes this this topic like
00:15:36.690 not trivial in groovy so for instance here we have user the new way we think
00:15:45.280 here in terms of classes and modules but in reality what happens is that user is a constant that that's
00:15:52.870 an expression it evaluates to a class object and that object responds to the
00:15:58.150 new method the return value of the new method is your user instance
00:16:03.820 similarly in date you have to think that's a constant forgettable classes that's a constant evaluates to a class
00:16:10.630 object that cause object responds to today the return value of that method
00:16:16.330 call is a data object that we store in the today variable okay so you know what
00:16:22.750 day today we talk about the string class you know and rewrite the string that's that's built-in in the territory it is
00:16:29.590 already in memory when we boot but a string is no it's not a special at all
00:16:35.650 it's just a regular constant like x equals one okay
00:16:40.950 constants belong to modules so every class a module you have just you have to
00:16:47.110 think that it has like a symbol table it has like a hash table of constant names map it to the values that's like like
00:16:54.730 literally that way so every class a module in your system has this little
00:17:00.790 collection associated to it that stores the constants so when we do this thing
00:17:06.040 class hotel and inside that module pricing class Hotel defines a constant
00:17:12.250 in which class or module in object so the top-level namespace is object I'm
00:17:17.680 going to use the word name space namespace is not a formal concept in Ruby but since we have we are working on
00:17:25.030 under the hypothesis that there is a project structure we can work with a
00:17:30.190 convention and we know what we mean when you say when we say they miss space in this context okay so the name is space
00:17:35.710 for for for hotel where is hotel stored the constant is 13 object okay so hotel
00:17:42.190 is a constant that has a class object inside and it's stored in that
00:17:47.740 collection of the object of object
00:17:53.550 module pricing is a constant that is going to be define it in the in the symbol table of the class store it in
00:18:02.170 the hotel Con okay so the the the main characters here
00:18:07.700 are class and module objects constants and storage is the module of the class
00:18:13.460 object in this case within the hotel constant that is storing the pricing constant whose Associated value is a
00:18:21.649 module object okay that's the way it works in we can alternatively you have
00:18:27.980 we have this alternative syntax in this case hotel has to be already define it
00:18:34.070 as you know okay and we are defining or reopening a pricing constant within the
00:18:40.460 class that is a store in the hotel constant okay that's the that's the full
00:18:46.250 thing any in this presentation is in the day-to-day you do not work may be that
00:18:53.149 way we do not thing you know with this position but for this presentation is important all right so we are going to
00:19:01.580 see very quickly it's not going to be reference just just a reminder of how constants are resolved in Ruby we have
00:19:09.140 this concept of nesting which is lexical basically the idea is every time you use
00:19:16.070 the class or module keyword you are you are nesting the class or module objects
00:19:23.059 respect respectively into an internal collection that the interpreter maintains is that that's not visible you
00:19:30.200 can inspect it but it's not it's just a lexical concept call it nesting so this
00:19:35.720 works doesn't seem to okay so in the first common ad in that in that line the
00:19:43.130 nesting is formed by those two things hotel column column pricing which is a
00:19:49.070 module object we see the constant we think constant but that's module object is just one single instance alright and
00:19:58.130 hotel which is the hotel class okay that's the nesting observe the object is not part of the nesting okay so you only
00:20:05.210 you only push things to the nesting when you use the class or module keyboard
00:20:10.279 there are other ways to do it but they are more skill not not needed for this presentation
00:20:16.059 in it is very interesting very relevant to to constant resolution that in the
00:20:21.639 second case where we use the the fully qualified name let's say the nesting we
00:20:27.340 are only using one module key ball right so that module keyword is pushing that
00:20:32.979 module to the nesting that's it so how Hotel pricing is in the nesting
00:20:39.070 in both places but hotel is not so when when when the resolution algorithms that
00:20:46.570 we are going to say to see now look for the constants in the in the in the
00:20:52.479 classes or modules is very important to understand that in the first case the
00:20:57.669 constant if it's in the place of that common is going to be check it in hotel pricing and also in hotel whereas in the
00:21:05.259 second case it is not going to be check in hotel because hotel does not belong to the nesting this is very important to
00:21:11.469 understand then we have the concept of ancestors of our class or module that
00:21:16.539 you will know that is the ancestral chain that we used to resolve methods you know this is the an example with a
00:21:24.369 string okay you can inspect that as well alright so very quickly just to have an
00:21:30.279 idea how we do we resolve relative constants so in this case we think here
00:21:36.519 we for instance in the example okay so easy you are you are you know when you
00:21:43.960 see the constant you want a certain place in the listing right like you see it okay so then the the algorithm goes
00:21:50.139 first outwards following the nesting from inside to outside so first you go the diagonal if the constant is not
00:21:57.639 found then you go back and go the ancestors up right diagonal first
00:22:02.919 ancestors then object is check it later
00:22:09.940 if if you are in a module because object does not belong to the nesting and does
00:22:15.609 not belong to ancestors of modules so if you use for instance the harsh constant
00:22:21.809 okay inside entire listing the first group
00:22:27.840 checks the nesting even if you think harsh this is like harsh okay that the global thing it becomes built-in it is
00:22:35.130 just a regular thing so harsh goes first to the nesting then the ancestors and if
00:22:40.470 you own a module it has to check object which is where hash is stored so it goes all this all this way until it finds
00:22:47.100 hash right finally if the constant is not found there's a callback call it
00:22:53.130 cons missing that is going to be called there's a default implementation of cons missing which is the one that raises
00:22:59.190 name error all right but you can override this then if you have a qualified constant like wrap request
00:23:06.360 here this is much easier so in this in
00:23:11.490 this in rack request we have like Rock the first the first segment that's a relative constant so rack is going to be
00:23:19.260 less resolved with the previous algorithm okay that's that's relative
00:23:24.559 but request is qualified and request is the one that is solved using this D
00:23:31.500 algorithm which is much easier it just checks the ancestors of rock upwards and
00:23:38.000 there's a technicality here for for object doesn't matter and if it does not
00:23:43.620 found cons missing so this is this is easier alright and this does not take
00:23:48.899 the nesting into account all right okay so how those rails out a lot know that
00:23:55.470 we know this you know that in rails there's this concept of outlawed paths
00:24:00.809 that by default has everything in a PP a PP models is in Auto all paths and the
00:24:05.940 auto load path represents object represents the top-level namespace okay and then rails defines a cons mission
00:24:14.100 hook so when a constant is not found that's autoloading right the constant is not is not found it is unknown at some
00:24:22.080 odd someplace cons missing is called so rails knows that the constant with this
00:24:30.179 name which is a string it was not found while I was in this class or module then
00:24:36.510 rails goes to the auto low-pass and sees if well
00:24:41.669 it has to it has to underscore the constant name okay so you got user capital u u underscore that user and it
00:24:49.799 goes it walks the outlaw paths looking for looking for user dot avi right if it
00:24:55.469 finds it it loads and under on the execution resumes alright that's the
00:25:01.139 basic idea there are many lines of code in the band's history but the basic idea is
00:25:06.839 that so the problem with that is that the the technique itself has on in some
00:25:14.119 intrinsic limitations all right so this attorney has been very helpful we we
00:25:20.489 have been able to work without without writing requires all these years so this
00:25:26.940 was a feature that I love it about rails and it's it's that kind of feature that
00:25:31.999 it's working for you and if if everything is going well you do not even
00:25:37.139 notice it just it is just there is doing its work you do not even notice but when
00:25:44.579 when it does not work sometimes it's difficult to understand why there's documentation but there are some
00:25:51.239 gorgeous so why it is limited well you in consuming you get the
00:25:58.200 constant name and and the class or module where this was not found which is
00:26:04.019 the nesting at that point you do not know it is not it is it is not in the
00:26:09.779 API economizing once the constant miss
00:26:14.999 it in a relative or qualified constant context you do not know so active
00:26:22.320 support just does not have the information to resolve the constant the
00:26:27.899 way Ruby resolves constants so the semantics do not match it does the best
00:26:33.989 that it can and it has some assumptions like I'm going to assume that the the
00:26:40.200 name of the module is reflecting the nesting it does you know some reasonable
00:26:45.389 assumptions but it just cannot solve this problem there's no information then
00:26:50.609 another one is the cons missing is the last step in this in this in this island in the in the indication
00:26:57.270 of what in in both cases is the last step in the resolution of algorithm and that that also by itself even if you had
00:27:04.200 these the first bits of data the third one is a still a problem and we are going to see know what why and finally
00:27:11.700 is not fret safe dredge has has had to work around that with with internal logs
00:27:17.220 and stuff right so comes missing is the last step why is that a problem because let's
00:27:23.880 suppose that you have Hotel class with module pricing okay that you have define
00:27:30.120 it in this in this second in the second file and your intention your intention
00:27:36.480 in the first file is to load your own pricing look the one the one is scoped to hotel right that's the one that's in
00:27:42.210 tension but let's imagine that hotel pricing is not loaded but you have a
00:27:47.580 pricing at the top level loaded because of the go path that happens in
00:27:53.130 development that happened available that can happen technically in an in an emote
00:27:58.140 what happens it happens that since Ruby is able to find a pricing constant
00:28:05.130 somewhere it is just not going to call cons missing it found something
00:28:10.530 it returns done all right and you get you get a class or module object that is
00:28:16.350 what it is not the one that you expect so so fundamentally limited is a
00:28:23.910 technique that is fundamentally limited so the hybrid uses a different technique it is based in module autoload maybe you
00:28:31.320 know model autoload this is this is the Ruby out a lot thing all right so you can in active record for instance this
00:28:38.220 is done this is used a lot in the rails code base you can say I'm going to
00:28:44.940 lazily load base basically active record base okay so instead of loading
00:28:51.270 everything you can say whenever you need active record base go and fetch please that file all right that's the idea so
00:29:00.350 the the new approach the idea is the following you have you have also the
00:29:07.230 auto log paths which are the the which we represent the root name is space object and then let's forget
00:29:14.730 about about namespaces for a moment just to understand the technique you have the auto low-pass okay so for instance you
00:29:20.910 have APB models so when you do setup you
00:29:26.400 go to APB models and cyberghost with new owners and lists the directory if it
00:29:32.550 finds user that'll be it sets an auto load call call in object to auto load
00:29:38.850 user and it does that for every entry in the directory okay that's the basic idea
00:29:45.390 then name is spacious complicate this a little bit and the API is bigger than
00:29:50.550 there are the small things that he can do but that Cydia right nevertheless I
00:29:57.750 have had this idea for years and there was some technical difficulties and it
00:30:03.390 was in in October of last year that there was a new issue about Auto loading in rails and it was like okay I'm going
00:30:10.020 to work on this I don't know how I'm going to solve it I know the technique that I want to use and I know they have some road blocks
00:30:16.890 but we we will get it ok so technical difficulties a module autoload uses
00:30:25.410 require internally so this is this does not work does not work well with reloading because require you know you
00:30:32.580 get if you require require is it important does it last thing ok so there is no API to remove out the
00:30:39.600 load and if you are reloading and you had an auto load that had not been executed to make things clean you should
00:30:46.500 remove that out a lot otherwise you could have unexpected loadings in the next request does not support namespaces
00:30:54.330 so you can say auto load one simple constant name you can put a qualifier
00:30:59.970 constant amino in auto load you cannot say in object auto load admin colin
00:31:05.580 colin users controller you cannot do that you need the class or module object the instance and set an auto lot for
00:31:13.440 that instance for the next level okay
00:31:20.490 and finally there's a chicken and egg problem with explicit namespaces that I am going to spray right now so all of
00:31:27.750 the salt require it that it important so
00:31:33.780 it has been a goal of the project to use to stick with Ruby standard ap ice and
00:31:41.790 to stick with Ruby semantics that's like a goal of the project so the project
00:31:47.610 needs needs a few hacks but they are very controlled controlled and they are
00:31:53.880 not like crazy for instance this is the first one how does require know if it has to if it
00:32:00.990 already loaded user or not it knows because there's a global collection call
00:32:06.270 it loaded features that that remembers everything so require goes to the collection and says do I have this user
00:32:12.780 thing if it's present then it does not it does nothing and returns false if it
00:32:18.210 not spread if it is not present then goes and requires the file and stores the fine name in this low that features
00:32:25.080 collections so the collection is mutable
00:32:30.740 we just remove the string from the collection and done so is this this level of happiness it's not like crazy
00:32:36.960 alright then there's no API to remove an
00:32:45.660 auto load but out constants that have an auto load semantically for Ruby they
00:32:52.950 they are not very different from from regular constants that are already loaded and it turns out that if you
00:32:59.550 remove Const the auto load is gone so solved then name is spaces we cannot we
00:33:07.260 cannot put a qualifier name right so these are another little little hug in the case of implicit namespaces we set
00:33:15.930 an auto load on a directory which is not documented it is not a standard use case of first Auto loading but it works so
00:33:27.809 so we set an auto lot an object on admin and then there's a very thin wrapper
00:33:33.700 around Colonel require cabinet require until two three I believe was not used
00:33:40.419 by Auto lot so when we say auto load uses require until 2.3 it was an
00:33:46.599 internal required different from colonel required and you could you couldn't access to that required that was a that
00:33:52.239 was a roadblock for it to implement in this but this changes so we have a very
00:33:57.489 thin wrapper around required nothing crazy just very thing and we intercept
00:34:03.219 you we know the directories we are watching we intercept and if you pass a
00:34:08.559 directory to that require it does it doesn't delegate to the true they actual
00:34:13.720 current require intercepts that goals defines the dummy module for you and does one step it goes since it has
00:34:22.690 already the module object then it can go to that directory or different directories because the namespace can be
00:34:29.260 split in different directories and does one level more that that's one interesting observation that as I work
00:34:35.829 in Auto loading mode is as lazy as possible so it's going to do only one
00:34:40.990 level of their first time and it is not going to descend on subdirectories unless you use them right then the
00:34:48.279 chicken and egg problem this was the last difficulty and I didn't solve this I copied this from from a gem from
00:34:54.339 Shopify and so the problem here is you
00:34:59.559 have an explicit namespace like hotel that wants to use one of his modules
00:35:04.900 okay then you have the module define it below right the problem here is that in
00:35:10.539 order to in order to evaluate the first file you need pricing but in order to
00:35:17.950 evaluate pricing unique hotel so what do you do here the solution has been traced
00:35:25.059 point so we set the trace point in the class even this has to be cheap thing and Shopify has a break in production so
00:35:33.039 no problem this is a
00:35:39.270 this is just an event that is triggered when classes are created or reopen it
00:35:45.010 modern source as well of course then the the thing is that we thanks to the trace
00:35:50.920 point we are call it so when so hotel is evaluated because you are using the the
00:35:57.790 hotel class somehow and then after the class keyword before the include line
00:36:03.430 you have your called so we are on time to go and the sin in that at that moment
00:36:09.370 into the hotel subdirectory and put the auto loads and then the next line pricing works that was the trick so with
00:36:18.040 that everything is solved and the gem is published all right
00:36:26.830 some final a slice to us to explain a little bit just a few ideas about the integration in in rail six this is
00:36:35.470 enabled by default in rain six new applications all right it has to be in
00:36:42.580 in C Ruby J Ruby they're working on that but for instance JRuby still has an
00:36:48.550 internal require for auto load so we they they working on that they're
00:36:53.920 working on that so is to be precise is right in rail six by default if you are
00:37:01.210 in Serie B all right so if you have this in config application to be low default
00:37:06.430 see stop 0 done that it's already integrated for you then very happy to
00:37:14.890 tell you that you can remove all required dependencies done so requires dependencies is going to be part of the history and you do not need this anymore
00:37:23.740 and if you are upgrading a rails application in principle you should just remove required dependencies and it
00:37:31.630 should work right ok it could be the case that you need to tweak a little bit in flexure in the
00:37:38.830 case of rails the inflictor is active support okay in the case of the default in flatter that comes with tyberg it's a
00:37:45.100 trivial thing that does like a split you know some one-liner that is super
00:37:50.440 determine dick no problem there's no configuration that is deterministic is under your control but in rails and then the natural
00:37:56.880 inflator for rails is active support carmelize and you may need to tweet in
00:38:02.400 flatter because the classic auto loader
00:38:07.970 receives the constant name and goes to the file system okay with underscore but
00:38:13.050 but LIBOR goes the other way around there first visits defined that the the
00:38:18.210 file the file system and then in first which should be the constant define it in those files that's camel eyes that's
00:38:25.440 going the other way around okay so these operations are not inverse of each other all right so a so the
00:38:32.250 capital letters HTML underscore gives you HTML all lower score but if you go
00:38:38.430 the other way around is not it you do not retrieve the same value they are not inverse of each other and they may be
00:38:43.470 for some acronym maybe you need something but in general it should work because we are using the same convention
00:38:50.820 that rails already uses but anyway recently I implemented this this little
00:38:56.580 check that you can run in your project if you are breathing okay you upgrade to
00:39:02.250 rh6 and before enable enabling the the default you can if you want run this
00:39:09.900 check and it's going to to the tech files that are not defining the constant
00:39:16.980 that are respected then you can go okay I need an acronym here I'm going to go
00:39:22.200 to the inflictor or you can even define your own inflictor okay you can do that
00:39:28.190 okay a configuration that is not in the release candidate it was it was pushed
00:39:33.660 after the release candidate but is going to be in final is that as I work
00:39:39.090 internally has a rule so there are several rules in the project one of them is that it is forbidden to do wall pass
00:39:46.190 forbidden cyber systematically uses only absolute file names internally so
00:39:53.240 there's no need for require there's only for require dependency and direc only
00:39:58.320 uses absolute file names internally so there's no need to have the auto log paths in low
00:40:03.940 the low path is the collection that Ruby uses to resolve relative requires right
00:40:09.460 so no need so I may be I don't know if
00:40:15.250 you were aware of that but a pppp model zippy controllers will be helpers daya in our total pass they are also in the
00:40:23.020 in the load path but we do not need that so we can we can you can opt out by
00:40:29.650 default is enabled because it has been that way since the beginning so but you
00:40:34.960 can opt out so with that you may save some hops in the resolution of relative requires by
00:40:42.160 Ruby itself and if you are using boot snap opting out of this saves also boot
00:40:49.660 snap work because it does not have to to go to those all those directories it
00:40:54.700 does not have to walk your project structure and also save memory saves
00:41:00.250 memory because it doesn't it doesn't need to build an index for all those files ok so that's an interesting flag
00:41:07.319 to take into account finally you can opt out if you are
00:41:13.059 upgrading and you say ok I have a lot of work to do we are going to deal without
00:41:18.520 loading later you can just say configure to other classic and you are using exactly the same alter other that you
00:41:25.210 were using in your previous version and finally there's going to be no the thing
00:41:30.970 has have settlin and and I epi has converged there's going to be documentation of course in the upgrading
00:41:38.200 guide and there's going to be a new constant guide covering saving all right
00:41:44.020 that's it thank you [Applause]
00:41:57.040 [Music]