Stuart Tech – Zeitwerk: A new code loader for Ruby with Xavier Noria
Articles,  Blog

Stuart Tech – Zeitwerk: A new code loader for Ruby with Xavier Noria


all right, so Zeitwerk is a code loader for Ruby
and these are the main features that the library provides it is
able to out load code it is able to eager load code reload also like we do
in in rails and it is designed to run in gems and in applications so for instance
if you do if you write rails applications there’s nothing with the
sound working good so if you if you write a rails application you know you
can autoload code you have been able to do that always
but gems well there was some solution to do something similar but in general gems
do not auto load code the same way rails applications to do that’s the thing
so with Zeitwerk that is that is possible you can write your own your
gems or any it doesn’t need to be technically a gem any Ruby project can
can have a I work as a dependency and outer load code the same way you do in
Ruby on Rails all right first of all let me show you let me show you how do you
use this okay first this there’s a convention which is
a which is that file names have to match constant names okay we do already these
in rails and if you are in a pure Ruby project let’s say that’s the convention
that the project has to follow that structure which which are very
conventional structure anyway so for instance top-level classes of modules so
if you have user dot there will be it should define user no mystery right if
you have user profile it should define user profile in camel case so we are
following the normal conventions in Ruby which other you have snake case in the
file system and camel case in the in the name of classes and modules HTML parser
good should define HTML parser but look at look at these lowercase letters
if that’s fine for you done it works automatically if you prefer that these
ones are uppercase there’s a solution for that because you can configure a
custom inflictor that is able to you know to to configure exceptions to this
basic rule right then the file paths match constant paths in the case of the
directories directories should match two namespaces okay in this case we have
something that I call explicit namespace which is that hotel.rb defines
Hotel and then there’s there’s something below Hotel Hotel::Pricing okay and that
should live here in a subdirectory so sorry you know in a directory called
hotel/pricing.rb that’ll be okay as we do in rails
I call this explicit because the hotel namespace has explicitly define it in
hotel.rb that defines the class in this
case but sometimes we do not define all the namespaces with an explicit file for
instance in rails you can define something below that are not an admin
directory and you do not need to define admin.rb with a module definition it
just works how it works because rails is there is no if there is not explicit
definition is going to define a dummy module for you with a name okay it does
that automatically and the iWork does that as well okay so we have the project structure
how do we use as I work very easy you instant it hello there you tell to the
load which other root directories of your
project for instance in a gem normally this is going to be leap everything
below leap has the standard structure done so one root directory in a rails
application is going to be a PP models a pp controllers there are several root
directories ok enrage you and going to need to do this because the rail 6 has
this integrated and the integration does this for you right but this is like the
bare usage of the gem once you have configured the root
directories then you run set up and set up does some minimal you know a starting
thing that we are going to see later in the case of gems indeed since normally
you have one Lib directory which is the only route that you have and also
there’s a convention in James Version that will be normally defines the
constant version everything in uppercase so it does some you know some small you
know convenient set up for for gem like loaders and it’s enough to do this but
you can also do the other thing in gems this is not necessary it’s just a
shortcut right ok then the basic API the small API and the readme has it all but
the basic is the API is this you set up the loader then you can autoload you can
reload if you want although normally only a service is going to reload so if
you if a service depends on five gems and the gems use fiber those changes you
serve normally those gems are not going to reload normally right and if you have
to blow up in a gem normally there’s no service running so you do write them and
maybe you run the test suite but that doesn’t involve reloading so reloading
basically is thought for services rails application and and
other web applications written in other web frameworks and in general anything
that that has a demon or something that is running okay eager loading is also
provided and this is convenient for production by default rails applications
for instance eager load the code in production when you ship a gem you could
say just eager know my code right eager loading needs Auto loading this is
something that sometimes you we do not realize but in order to eager loading is
not just required recursively that that wouldn’t work in general because of
files you if you evaluate a file it could be the case that at the top level
or a class level you know in the execution path of that evaluate you are
referring to other constants so in order to load in order you should have you
usually need to have like a dependent dependency graph of everything that is
used everywhere and we do not have that so you cannot just recursively load you
have you have to have Auto log set in order to be able to either load a
generic code base at least right so thanks to having auto load we can eager
load any project that that follows the conventions in the files in the file
structure which is a the only thing that we need finally there’s a there’s a
method by work registers all the instances that are created and then you
are able you have API to load to either load them all that’s convenient for
instance in production in a rails application you want to eager load as
much as possible on boot ok then no matter whether the the dependencies even
loaded or not you are able to say eager load the code of the application
assuming that is using Zeitwerk and also eager load the code of any other gem
that I depend on that is using is a verb so in general you are
going to put the main process with as much as possible things low that and
this is in general convenient and you’re going to load things earlier
copy-on-write memory benefits and that kind of okay again in a rails
application you do not need to do these rails does this ok the integration does
this okay which is the motivation behind syverud the initial motivation was the
last one improve raise autoloading why because if
you are raised firmer you know that out loading in rails has some edge cases is
from gocha’s it it is practical it has been used for many years since the
beginning in it but he has some coaches it doesn’t follow
groobie semantics and that’s the main thing that doesn’t quite a square but it
was the best that that we had okay so I wanted to improve result logging but
once I started working on that I realized that this could be generalize
it and address another pain point of me at least which is that writing requires
manually is brittle in in Ruby projects okay in rails you do not feel this that
much maybe because precisely you do not write requires in graves
everything is autoloader that’s the magic Tory that the cool thing but if
you if you have written any non-trivial Ruby project you know that this is
brittle what you have to write requires is brittle dryness in in general in
generic Ruby projects well that’s also a perception of mine if if I have a user
dot avi file and I need to tell Ruby require user I have a sense of
duplication okay I so if all my files correspond to constants
in an order that way I am always I’m always repeat repeating myself because
everything is order it what everything has a one-to-one relationship between
files and constants so when I need a constant and I need to to put again in
in in a snake case the fact that the require for the constant to be available
in five I have a feeling of lack of dryness I could I could solve these
remove these with combined unit with a convention okay a convention which is
pretty natural otherwise that’s a pet peeve of mine
okay maybe up for the people which is not a problem you’re right requires and
fine but this is something that I want to say what so for myself let’s talk
about requires for a moment so for instance let’s say we have a locatable I
believe this is pronounce it module that I don’t know for coordinator or
something you know and you have a class with an airplane and that includes this
module in a pure Ruby project this shouldn’t work you are going to find an
intelligent constant locatable why because you have to do a require you
have to you have to remember that you have to put a require okay
require is going to if to load this file if it was not already loaded and this
file is assumed that defines the look locatable module all right so it’s going
to be available in this file all right but the problem is that require has a
global side effect so if you require locatable this is not a compilation unit
let’s say this locatable is from this point on available in the beautiful
machine everywhere it’s just a global global thing it has a global side effect
what happens that this we thought the require could work if someone in your
code path before you reach this point load the module
is going to be available and you do not notice you notice when in production you
you hit a different code path and you have a constant missing okay it’s super
brittle you have to be super discipline it remembering everywhere you know that
every constant that you should have the corresponding require all the people
instead of putting requires you know selectively in its in its files decide
to put them all in the in the main file the main entry point position this is a
nano see which is a static site generators ok nano see decided instead
of putting all the requires in every single place well you know what I’m
going to conceptually eager load everything this is this is the the main
file man entry file of the other term conceptually eager load everything and
everything is available everywhere of course you can you can see that this is
not is not this has a cost no when you create a new file you have
to remember to go here and also this has to be has to disk this has to be there
has to be an order here you cannot put it anywhere you have to you have to
respect the dependencies between these files so this is doable but also has a
cost in that sense so just delete all the shit ok so this is the Nano see is
using the I work just delete everything instantly ins ever done I love this
patches when I saw it it was like yes that is not that’s the thing so that’s
that idea you can streamline your programming you you just forget about
this problem just name the the constants according to the file names isn’t it a
loader setup done your classes and modules are available
everywhere that’s that’s the thing okay Auto loading and loading in general I
tend lately to speak about classes modules and namespaces but in reality
technically we are this is all about constants okay and knowing how it works
regarding constants is key to understand how this works and when you have a
problem to understand where the problem comes from so let me let me just give
you a quick refresher about constants in Ruby to have more context about the
problem so you know constants in Ruby one identifier at the start in uppercase
later is a constant which is like a variable a variable but it is not
supposed to change you know constant pretty common concept normally pretty
trivial concept in any programming language but in Ruby is not trivial at
all it’s not it at all because it is it is being created with classes and
modules in a way that so classes modules are objects they are an independent
entity and constants are storage but there’s a coupling between the two of
them because here we have a constant assignment as well it is not obvious
that is it is so this is clearly a cost an assignment right this is also a
constant assignment it is the same thing as writing this so C here is a constant
thing variable is a storage there’s no syntax for classes or modules in Ruby
okay so here we had one assignment to X what we have here is a class object
assigned to C so C just stores in one slide is a story so is a story no one in
this slides Estonian a class object is a different kind of object is exactly the
same thing from from this point on C is a constant and C can be remove the class
object can be in another place they are totally
independent entities for instance this is super key when you see this code we
in the you know a day to day we we see here you get the user class the day
class right but if we stop and think for a moment what happens here is that user
is an expression user is a constant the user constant evaluates to a class
object and that object responds to the new method the return of this return
value of this method is a stored in this variable same here date is a constant a
by the way to a class object that responds to today the return value of
this we store it in a value so when you see this in the day to day within within
classes okay but in reality in reality technically this is just a constant that
evaluates to something we could have this class object a store it in a
variable we could have this class object store it in a different constant okay
they are totally orthogonal concepts constant belong constants belong to
modules like physically like top-level constants belong to object and if you
have a namespace the constants within that namespace belong to the class or
module that defines the namespace for instance here we have class hotel that
one is going to belong to object then we define within hotel module pricing the
cons the pricing constant is going to be stored in the whole in the module that
is a store in the hotel constant that’s all the thing right so this thing is
going to be long the thing has many module has many constants and it’s like
is you can imagine that internally you have like a symbol table
table where the name of the constant maps to the value that is stored in that
constant and this map of the symbol table is stored in the module and every
module has his own its own symbol table like that so this this pricing constant
that belongs to hotel has nothing to do with a hypothetical pricing constant
that is our top level if we have the same name there are
totally different objects pricing at the top level it belongs to the system table
of object let’s say while this one belongs to the system table of hotel
there’s nothing that they have no relationship we have an alternative
syntax to define that like this this is the same thing defining a pricing
constant within the module that is a storage within the hotel constant okay
we are going to see how constants are resolved very quickly to introduce that
let me just explain very quickly what is nesting which is important for that
resolution algorithm nesting intuitively if you see so I’m not going to do to
give the full technical definition but for the day-to-day it is enough so to
understand that when you use the class and the module keywords like this and
you and you put things nested like nesting namespaces when you arrive to a
point the the classes and modules that are in each of these levels become part
of the nesting like this so the at this point the nesting is Hotel pricing which
is this one and hotel which is this one okay object which is at the top level
does not belong to the nesting here this is different we only have a module
keyword here right or there’s only there’s only one one one level of
nesting this is very important because the the way things are resolved it is
different here why because the nesting here has only one module this one here
we have two because we have two levels but here it doesn’t matter that the
constant has like two segments it doesn’t matter at all
you have one level of nesting that’s it that’s the nesting only one module okay
here we see the name of the module printed but these things are objects
like the module object the module or the class object you know okay so if you see
a listing if a new wonder which is the nesting at some point just go outwards
this indentation and that’s that’s what confirms the nesting the other one isn’t
and the ancestors the ancestors basically of a class of or a module is
the the chain that you have upwards with include modules super classes if you are
working with a class and that’s like linear alright so for instance ancestors
of a string string itself so this this this guy is belongs to the ancestors and
if we have if if this had prepended a module ëgod it would go indeed before
the same object compatible which is a module right object
these are the ancestors for instance this is used when you want to resolve a
method okay this is this is going upwards so if the method is not defined
here you look here otherwise you look here this is ancestor chain okay so we
are ready to quickly revise the algorithms for constants there are two
cases there are a few more aids but these are the main ones when we have a
relative constant like for instance when you say a string in the middle of our /
/ / listing all right Ruby does this first checks the nesting
that means that the nesting is confirmed by classes or modules right so Ruby
checks the first element of the nesting the constant belongs here let’s imagine
the answer is no it checks the next in the mast in the nesting is the constant
does the constant belong to this class or module let’s imagine the answer is no
he goes to the oldest the nasty old words if the constant is not found in
any of these class or modules then it goes the ancestor chain upwards so we
first go in diagonal nesting then in vertical ancestors there’s a
technicality here that is that if the mod if the inner module in the nesting
is a is a is module then it also checks object alright and that’s why if you if
you refer to a string within any place you know in a module you find a string
even if a string does not belong to any anyone in the nesting and it does not
belong to the ancestors of modules because object is not an ancestor of
module C so you need this a special rule in order to find to find tolerable
constants finally if you do not find the constant in any of these places there’s
a callback call it cones missing that is collet and it says cones missing I have
not found this constant the default implementation of cons missing is the
one that raises name ever but you can override that then if you have a
qualified constant like digest md5 in digest md5 we have two constant here
digest is a constant and this one is like it is written here this one is
relative and good be resolved with the previous algorithm md5 is a constant if
that is qualified with with Colin Colin so this one has a different algorithm
which is much simpler you just check the ancestors of this guy up that and the
it calms me seen as a 4-1 okay there’s a there’s a technicality that object is
skip it but not you know right basically next thing so relative is nesting
ancestors comes missing and if it is qualify it you don’t you do not check
the nesting at all just ancestors and kata missing basically that’s the idea
okay so we are ready to understand whole race auto loads as a summary at least in
reg we have something that we call the auto load paths that represent the root
directory is the root name space object okay we have this and and in auto load
path by default anything that is a subdirectory of a BP is there so a PP
models is there a BP controllers it will be helpers whatever okay and race
defines a cons missing that implements the Auto loading oil is the entry point
to the Auto loading so what happens in rates if you have users controller and
users controller defines or uses sorry I use it the user constant like in an
action you say user fine params IV you know use you are using the user constant
what happens if you if the user in class is no load that this algorithm is going
to go to cons missing because the computer constant is is not known and
cons missing is going to say okay I am users controller and I am told that user
a string the name is missing then rails goes and works the the outer loop paths
looking for a Doozer floater be if you find that you should re-evaluate the
file with load in my default in development mode and as a side effect of
that the user constant if everything is okay is going to be loaded and then you
continue the evaluation of the the code but this technique has
limitations and that is why we do not have Ruby semantics in rails fully Ruby
semantics for instance the nesting is unknown you
do all the information that you have is I am users controller and someone wanted
to evaluate the user constant here which is the nesting at that point no clue
because Ruby doesn’t tell you the callback the API of the call that yes
receives self and the name of the missing constant that does all the
information you have so we saw that the nesting bill is part of the resolution
algorithm and we do not have we do not have it so it does a fundamental
limitation of the technique that race has used since forever we do not know if
the constant missing was relative or qualified and in general there’s some
special rule but in general you have to assume that grades since it doesn’t have
that information is going to assume that that it is relative okay this one too
soon that then consumed missing is the last step that is important for instance let’s say you have like an example
before class hotel and includes a module called pricing and your intention is to
use the hotel a slice pricing okay but what happens if we have a top level
constant pricing that that is table level it has nothing to do with the
constant you want to use but it is define it what happens is that since
Kahn’s missing is the last step Ruby is going to find in the in this
algorithm is going to find the top level one I got one
here this and it is not the one that you want you would like to overload the one
in hotel which is the most specific one but since the since Ruby is able to
resolve pricing to some constant that it is not going to call cons missing so
cons missing Bay in the last step is also a source of some gorgeous finally
it’s not thread safe so in grace rails has been let’s say for a while but why
many years already haha but in development mode for instance for
autoloading rails is set some locks and some staff to be able to be thread safe
in production mode normally that’s not an issue because you can load everything
so there’s no there’s no point to be out loading normally normally in production
okay okay let’s keep this one no this is
whole rails works and these are the limitations of the technique Hodos
diable work because as i will solve that there it relies on on module auto load
module out load it that that’s something that comes with Ruby
alright say you have these module active records you say outer log base and a
string this means that you we are defined out active record then we are
saying if you in any place one to access active record : : base Ruby is going to
intercept that and is going to go and require this fight for you so this is a
way and this is in the in the Grails codebase
that’s use it a lot it is a way to defer loading the file until you use it okay
so that’s built in individual machine and when is one when I explain when I
explain it the algorithms for custom resolution I skip it one step which is
that every time Ruby checks in a class or module if the
constant that is resolving if the custom belongs to that class or module actually
it says let’s say conceptually do you have it in the symbol table if the
answer is not then still there’s a second question do you have an auto load
for it and if you have an auto lock for it is going to execute out a lot so
that’s built in in the beautiful machine and that matches semantics why because
it’s injected in the India in the actual algorithm so it is going to find the
constant the one that the work that the one that you want because in every step
is doing this checks for out load but all right yeah so the same idea you have
auto load paths and the the thing is that when we run setup when we when we
sent it the loader and put set up the load that is going to walk one level of
those paths and it’s going to the it’s going to say okay you have user dot
there we I’m going to set an auto load for the code for the user constant that
that if used is going to go and load user total B that’s that’s the basic
idea is this then from from here to the implementation there’s some stuff to
resolve but that’s just the basic idea and that’s amazing and because if this
is possible this is using API and logic that is built in the before machine and
why it works because the merit is from the below machine
we are just leveraging you know this this contract so would you work the root
directories and set out loads for every one of the constants that should match
the file names that you find that’s for the top level
there are some technical difficulties nevertheless with this approach modulo 2
load is something I had in mind I have had in mind for many years because when
I I have studied this topic and it was like oh man if we could if we could use
model out a lot all these problems would disappear but there were some technical
difficulties some you could work around some you have been able to work around
later for instance module autoload uses
require internally that does not allow in principle to reload code because
rails is able to reload code because it does not use require and development
mode by default it uses load load is something that is provided by Ruby is
not very common but load basically is execute this file no matter if you
already executed this file is just go and evaluate this file load all right so
in the middle mode reduces load when you want to reload if you say load user is
going to load again user if if you if you instead of load use it require to
load user because traits in the end you have to load the file right so if you
did require user the second time in reloading that you used to require
require I would say this is already load nothing to do and you could you could
not reload so in principle this is a problem okay
but in Sabre keys publish it so we have solved it everything that’s here right
let’s give it just a little bit of mystery right there’s no API to remove
out a lot so you have you can you can set an auto load but there’s no API to
set remove an auto load right and this is important because if you are loading
for instance and you had users that’ll be in some place and then you want to
reload and you remove that file and you have a user to their be in another place
with different contents you would like to reload to auto load that other one
but if you do not remove the auto load it is going to is going to look for the
previous file that that that couldn’t be correct okay
so you have to be able to remove outer loads also it does not support
namespaces in the sense that you cannot you cannot say in object out a lot admin
: : user you cannot say that you are only able to our set a note a lot for
one level so in object user and then if when you load admin you are going to be
able to put an auto load for admin for this for the children of admin but you
cannot you cannot pass qualified names to opt a lot only one level the other
ones chicken-and-egg problem that this was the the most difficult one for me
and I am going to explain that one later alright let’s see let’s see how we work
around those difficulties so as we as we know if you require a user and then
require use again the first one is going to load the second one is going to do
nothing because it is already low that’s the contract of require right okay how
does require know that the file was already loaded because it has a
collection of the files that have been already loaded call it loaded features
okay so it goes to loaded features well it has to resolve this right you get a
full path or whatever and you go to load features and see with the file belongs
to load features if it belongs for false if it does not belong you’ll load and
true all right so that collection is mutable if we modify the collection you
are able to reload ring okay this is an old trick that imperil plan it’s been
known for forever and pen you have a value who you hack everything so yeah
first first one solve it okay we mutate other features it has been it has been a
principle of the of the development of the library to use as less hacks as
possible so the library on purpose as much as possible on a standard API
from groovy the hacks are super super minimal super justify it and I believe
not not rare like this level this level of of hacking right and this works this
is the I mean I don’t know if there’s documentation that says that you can
mutate this thing but it could be very strange that these changes so just a
little hug ok remove the file you are going to be able to require again
because there’s no way to say to autoload that it should use load there’s
no API for doing that now and this that’s you know written in the in groovy
and there’s no way to around that so this is the workaround
removing out to loads well there’s no API but if you remove the constant even
if the constant is not properly loaded that remove out in fact that removes the
auto load so this is enough okay and indeed something that I have learned
writing this library is that for Ruby an auto load and a constant that has an
auto load more or less for Ruby is as if the constant was define it so all the
API works alright now we said you cannot put an auto load for a constant path you
have to do you have to go one step at a time
so let’s let’s imagine that we have an admin directory what do we do okay so
the I work one when it does the work it says ok we have a directory here and
this day and there’s no admin that’ll be only a subdirectory so what we do this
is Joan so al-haqq is we set an outer load for the directory this is undefined I mean you can put out
loads for files but for directories but it works what happens that when when
admin is referenced autoload is going to require this file and then we have super
super thin wrapper around kernel require that says hey this is the directory that
I managed so we intercept that call with the sub that call in this case we define
a dummy module like rails doors and then Cyril goes to this directory or
directories because admin could be define it in several directories and
those one level more and set out loss to this admin module that it has been just
instant ated and this is this is the tricky one and I did not solve this one
I I copied the solution from another gem all right the thing here is you have an
this is call it I call this an explicit namespace in the sense that in the sense
that the hotel class defines the namespace and it has a file that defines
the this class all right what happens here is a chicken-and-egg problem
because you cannot you cannot evaluate this file because this pricing is not
it’s not ready for for for having to have this pricing ready you should be
able to have the hotel class in order to be able to put an outer lot but the
hotel class is the thing that you want to have as a side-effect of evaluating
this file you cannot go here either because you
need hotel so you cannot you cannot evaluate and your any of the two they
have a dependency between the two all right so to solve this we said traits
points on the class event trace point is on API and
several types of events that you can listen to this is the one that is
triggered when a class or module is created or reopened right so basically
the idea is that we set a trace point to listen to creations and we and we
register that we are interesting precisely in hotel what happens the
thing is that we are able that way with the trends point should be call it
precisely at this point before that the class body
is been executed we are call it here so since we are call it here
the callback that we instantiate this block is going to be executed we are on
time to go to the directory and set up the load so when when we reach this line
the load set that’s that was like when I thought this was possible was like okay
we have it all right so to finish the presentation the integration with rail
six which is I’ve tried to integrate this in a way that is as transparent as
possible as well interested as possible so in rail 6 is going to be enabled by
default in the in races you know you have two ways to auto load the plastic
way and the Zeitwerk way so if you generate an application a new application in rail
six is going to have this this line in config application that will be and load
defaults 6.0 is the code that sets the I work as a as a default auto auto load if
you do not have these defaults but you are upgrading to rail six you still can
set it as well but what this is the default done that way
this is API to be able to trace the activity of the elders something if
you is sometimes if you want to troubleshoot something this is very
convenient just throw this in application that there be and all the
activity of the autoloader is going to be logged in this case so this this
accepts a lambda and accepts a logger object as well okay if you pass a lambda
like this this thing this is a trick to get a caller well here it just calls the
caller ball with a method with a with a message if you should a logger it uses
it uses the debug method of the logger but this is super convenient and you do
not you know you do not leave this permanently okay so it’s just you know
you troubleshoot something and then delete this line does it then it could
be the case it could be the case that you have to configure on some inflection
because we are going in the opposite direction of the classical Toller so the
classical troll in confessing you get the constant name and given the constant
name in camel case you inflict and go to snake case and look at the file system
so but Zeitwerk goes the other way around so I will start at the file system and
says this file should define this constant okay so underscore and camel
eyes I know this is not a rejection okay you
cannot the one is not the inverse of the other one in the common cases they are
but if you will start to use acronyms and that kind of thing they are not they
are not the inverse of the other one so for instance it could be the case that
you have some HTML or some API something you know and maybe you have to say in
the flexors look API is an acronym HTML is an acronym okay to have it to have it
inflected like you one you can also rename the class you know one call it
today and you know and and you have HTML in lower case and that it you know but
if you have some you know the difference with respect to
the previous altar loader if you are upgrading an application maybe you have
to add something here yes no well not really because what happens is that the
constant is not fun and that’s it the constant well what is going to happen is
that you are going to refer a constant that for which there is no auto load so
the I burg is not able to intercept that and Ruby’s going to say I don’t know
this constant so yeah that’s how it works you say HTML parsers not fun
oh I have an HTML parser then you have to realize that that the inflection is
different and then there’s also a way to upload so that’s the default but if you
if you are for instance upgrading and you have a you know work to do to be to
you know for whatever reason you can still you know use classic this way and
this is this is going to be exactly the same thing that you had before ready six
yeah all right that’s it thank you okay we have a microphone so if someone would
like to ask any question just raise your hands for the last slide is there a way
to do it incrementally like I want to use side work for this folder and I want
to opt out for the rest of it so you can know like incremental migration will
migrate eternal six no clásicos ever does it
cool any other question yeah so read on a question from the online viewers which
is cool DS Auto loading approach be added as a language feature to Ruby
itself oh man I love that so the problem is that the fundamental problem is that
in Ruby there is there is no relationship between class or module
names and file paths it’s it’s flexible in that sense this is the way ruby is
designed there are other languages that do not work that way
for instance in java class the class files have very very strict structure
that matches the name of the class and if you are willing to write the fully
qualified name of a class you do not need to do anything it’s available as
long as it as it is in the class path is available in Erlang the same thing in
Erlang you just use modules and Alexeev the same thing we just use modules you
do not have this require anywhere so why because since there’s no option your
module name has to match the file name of the compiled file there’s no option
then the the language can rely on that and give you outer loading because in
the end they are Auto loading right so since Ruby does not have this we have
required we have all these this way of doing things and this is why Seibert
requires the project structure and I would absolutely love that Dybek was not
needed I will surely love that that Ruby does this and you know and and and it’s
something built-in but that’s something that that belongs to the to the Ruby
core team and I believe it’s very unlikely because ruby has been working
with this with these contractions whatever and I don’t think it would be
reasonable to suspect that these changes but I could both +12 that thank you and
the second question is what what will be the migration path for rails 5 app
alright the migration path good so in general is going is in general should
work for the majority of classes or modules if you have follow it so the
good thing is that we are using the same conventions that I use it by rails so
since we’re using the same conventions the application is going to be ready so
the migration there’s not enough there’s not a lot to do things that that that
you can put that you could consider first that maybe you need some
inflections like like I explained it that could be something and I know that
something sometimes happen is that you discover that your application was
resolving a constant that shouldn’t be resolved because it’s used in a place
where Ruby should not find that constant but because as I said classic
autoloading assumes in general except for some special rule and that the
nesting with the the name the fully qualified name of the constant reflects
the nesting for instance so sometimes the classic autoloading finds a constant
that Ruby I I’m not going to say that it shouldn’t it shouldn’t find it because
classic works this way these are the room so it find it finds the constant
according to the logic of classic let’s say that Ruby would not find that that
constant so since I burg matches Ruby semantics the constant is not going to
be found okay that that’s that’s from its case
and I am going to document that in there’s going to be a guide for this and
and also there’s going to be an upgrade guide like like rails also always have
and in the in the great guide I am I am taking notes of some people that have
done upgrades and there are some super edge cases that I’m going to document
but you know apart from that should be seamless seamlessly I don’t remember how
to pronounce this it should be transparent let’s say thank you yeah
hello Terry are you planning to ask for some change
in the Ruby API in order to avoid doing that that that hacks on favor well
there’s one thing that maybe I tried to open at least an issue or send a patch
which is that this is this is something that is needed inside implementation so
basically there’s there’s for instance API to say does this module has this con
have this constant the scones define it okay you can say the string cons define
it something and if it’s define it it’s going to say true otherwise false okay
you can pass to that a flag that says please check also the ancestors
so basically could be if if I if I write a string column calling this constant is
going to give me something if you check the ancestors that’s what does it
but you can stick on you can pass false as in that flag that means I am only
interested in knowing that this if this constant belongs to this particular
module exactly in the in the symbol table of this module do not check the
ancestors okay all right Zyra needs that also for outlaws autoload question mark
so there’s a method outlawed question mark that tells you if there is an auto
load set for a constant and we use that internally so that method does not
support that flag and that method always check
checks the the ancestors and and what the logic of Dybek needs an auto love
question mark that has that that is able to ask for do you have to you exactly
this module has this auto load said we need that the API is not there I am sure
it is doable because cones define it has that logic show I guess it’s just not
written okay so what what divert does is implements this you know internally okay
so if we don’t have the question thank you thank you for your talk
excellent right Thank you

Leave a Reply

Your email address will not be published. Required fields are marked *