Ruby on Rails #55 Subdomain Multitenancy with Ernest Addae

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
because uh from like all the rails implementations of sub domains uh i liked yours the best i was really surprised like it works really smoothly so i'll create a new app so that we can what we can work from it from scratch rather than trying to go through and resisting up several moving parts and stuff like that yeah definitely yeah um usually create an nu rail 6 app is uh like five times longer than creating a rails five new application yes and and the the also the up becomes already the app becomes already big you know like the size is very big but i i tried so i tried hanami when they announced their version 2 launch i think it's pretty cool it's pretty cool but it's down that everyone is so much addicted to rails that is difficult it's quite difficult okay so i open in a text editor okay so let's see if everything works oh wait sorry about that i i remember i used i'm using postgreso as usual i have to set it up before and then let's see if we are on course okay it seems everything is set okay so uh so let's say you uh i think the whole the whole premise of a multi-tenant tenancy app is to have a main account uh whereby you scope all your resources into that account right i mean that is the idea or you can use the apartment gem approach which i find very difficult and i don't even understand so i'll not even go there but uh the one that you can use as tenants or try to scope tenants uh i find it quite the best approach in doing things so let me start by generating an account okay well i mean the approach where you have just one database is uh always uh much more pleasant than having different schemas or different databases for each tenant yes yes i i think that is uh i mean if like you are running a giant business that has billions of records uh maybe it makes sense to use something like apartment gem and use separate schemas and yeah but the downside is scoping each one of them by using their has many relationship it's just that uh the downside is you always have to remember that whatever new resources you are creating you have to scoop into our account sort of yeah i think that's the only thing so let me create my the root route i'll start the server and make sure that we are in the roots our homepage is the same as we are so that we can go on okay so normally you create a new account yeah so basically is this right so the normally this is the normal route that we go about it but now we want an account to have sort of like a subdomain so that when we create an account we will go to a subdomain and access the uh the account so uh how we how i did it is by having a sub domain first right so that we can use the sub domain as the approaching uh as the way of scoping each of the resources we have in the account so how i went about it is to first create a subdomain so [Music] yeah this is better yes so let me create a sub domain right so now we know that we have the sub domain i'll go to my controllers and then make sure i allow the sub domain and then i make sure i have it also in my my phone okay so now now that i have it set up all i have to do is to go to my controller and whenever i create um whenever i create a new account i will rather redirect to root url but i want to be conversant of the sub domain so i have to do the account and then tell them that okay whenever you are doing it i want you to go to the sub domain as well for me so when i create an account and it's all right it's come to the sub domain and if i not so the request the rails request to when i created to just route the request to that uh that sub domain for me so i will against that my server uh you have redirect to twice in your controller yes yes uh come again uh you have the vote redirect to twice in line 28. yeah oh yes thank you thank you yeah so we redirect to the root route and then i'll go i'll choose the sub domain and i want to go to the sub domain of that so i will come to my app now so now when i create a new account another and i go to another it redirects me to the subdomain so you can see the route here it has moved from the account the sub domain name i gave and then the localhost and stuff but usually developing this on localhost this should work all right but the problem i discovered is that even though everything worked in the development environment when i did it this way um when i went to production i had a little pain with that so i learned that you can actually use lvh dot me something of that of this plus it serve as a sub domain already because we have lvh dot me already so this one is seven at the root domain so we can add your sub domain to it so i just go to um then go to apple uh config application dot rb and white listed yeah and then white list so normally uh our whites left the list this or i would just set it to nail so that i wouldn't have to be updating the route anytime i try to start a new uh i'll try to go to a new route so with it i'll start my server again and then when i go to lph 3000 the link is available for me then so when i create a new account so just reroute that so here this is more representative so i get my sub domain name my name and then the this one so with this one what i realized when i did it this way uh it worked in production as well as in development so i learned that the lvh dot me is actually a pseudo for localhost 3000 you know so if it's an alias to localhost 3000. so i've heard this again it's a dns label to localhost 3000. so i i i must mention that this is very very important else everything working look out in development but then when you go to production everything is something else okay so now that we have the sub domain here we have to consider another thing because at the end of the day our app has to be scoped to a particular resource so let's say we have uh like a post or so whatsoever right so let me quickly just say we have a post for each of the uh posts for each um account to have many posts right so we can generate the rails uh scaffold i will call it post has a name and it belongs to an account and it belongs to an account yes yes oh yeah uh okay so now i have it this way so i can go to my i'll go to the model account and then pass many posts just in case and then a post will belong to an account right okay i think i forgot something to mention here uh that we have to make the so that we don't end up generating well south dominar we should okay so now one this is set up now we know that um a post will eventually have many uh uh an account to have many posts and i propose to belong to an account but then we also want to make sure that once we go into a post we can have the resources that we want because we don't always have to be generating the post so we need a way to make the sub domain be required which now we can click a link and then we can go to the subdomain right so we need to set uh a current helper method to track the sound domain for us so because when we have let's say you can have several accounts but when you click on each account you want to go to a stop domain of that account that is actually pretty much unique to you right so to do that i normally i try to set a base i don't like using an authorization like pandit and tank and can much so i normally try to develop a base a base controller and i make my key controller inherit from those base controllers so yeah right but anyway but for the for simplicity's sake i think i can um let's define our route into uh in the application controller so that can control all so um i generate a i'm edited like current account and then i'll minimize it to account defined by i want to find by the sub domain so whenever you make the request i want the request to be routed to the sub domain and i want it to be a helper method as well so with this case what i do that once i list all the accounts that are below if i want to find a specific account i can just quickly go to the sub domain of that account and then i'll just find it so that i wouldn't have to be declaring it uh anywhere that i go this exactly am i making am i making sense yeah yeah that's answer oh okay okay okay okay so now uh now that we have the account set up we need to be able to scope it we need to scope the we need to scope the account so that each resource can go into uh each uh account so i use the rails scoping so i scope the module account and then i try to put the resources in there okay so for instance i can make let's say i can declare the beauty of having scope is that i can be i cannot declare two route routes for myself as well so i can say that through throughout of the sub domain uh can route to let's say hosts uh index uh this way right so i can now have uh two uh scoping mechanism but then the downside is that now that i have a scope i have to i have to create the scope as a folder within the controller so i have to create a new folder for accounts right and then within it i have to create a post controller as well so in this case i will just wrap my module yeah so now i because i have scope it i cannot wrap everything within it so it's really not much of a problem because all i have to do i can now come here and copy virtually everything as i have here and put it inside the scope and make sure i wrap it so when i do it this way it means that now every route that is in here will be scoped to the post uh controller as well as the same as as i have without the scope however the downside the reason why i don't really like declaring all my this controller within the within uh the application main controller is that i want to be able to control the things that i do within the scopes that i have so usually what i will do is that i will create sort of like a base controller so i would do it i would i'll use this as my my base controller and then fetch everything that i have here and leave the application controller alone because it's something i don't want to touch so yeah so i used to i i've declared this so that i know that whatever happens is limited to my it's limited to uh it's limited to my base controller then what i'll do is that i'll make my post to inherit from sorry i'll make it inherit from the base controller no sorry account sir yeah so once i do you made you made the typo in the word accounts yes thank you thank you fair programming thank you yes yes so now that i have i don't have to worry again because now everything i want to do is going to be is going to be inherit from the base account so my post is inheriting from the base account which means that everything i do within the base account as long as you're inheriting from the base account you are solid so i don't have to worry about my uh my uh how do they call it my application controller uh account uh please i hope i may have made i'm making sense so far this is my first pair programming so like i'm like nevertheless also making me more nervous you're doing great okay thank you so uh with that done i think that another challenge we have to face another challenge we face is that um if we try to go to we have our route defined here right but uh we don't if we want to do it this way then it means that whenever we have a sub domain we have to be calling the sub domain to always be calling uh the uh to always be calling our resource which means that when uh the point i'm trying to make is that let me go to my accounts controller right so which means that anytime i go to a new route i may have to define a sub domain all over again even when i have a new resource i have to define it so it's kind of like a waste of time and you may also do the you may also have a typo and you may also forget to do something so what uh i did was that uh rails give us the opportunity to actually do the rails the race routes constrained so we can actually constrain whatever route that we want in one place so for instance what i mean is if we can call let's say posts have in under a sub domain but at the same time we can also call it uh in another uh another place that is not a sub domain so we have to do the rails corner stream so that's where rules comes in with the the routes constrainting so what i did was i went to my left folder and then i created a folder called sorry about that constraints and then within that constraint i define a file called subdomain must require so i define a class called subdomain repair and then i use uh there is um rules of i something i read from here mm-hmm it's something yeah the hpp http constraints so actually we can use the request as a hack into going to wherever you want to go so actually when a request is coming to the route we can reroute it to the sub domain that we want and the way we do that is by using the matches uh keyword careers offered to be the matches keyword so i came here and then i just have to define the the match so i'll i define a match for okay def self dot matches requests okay so what i'm saying that if the request has a sub domain present right and then the sub domain uh the request sub subdomain is not directed to www right this is what i want so i wonder okay one of my requests is coming i want that request to be within the stab domain as long as this request is now within this is it's a subdomain and the subdomain does not directly point from www dot this is how i want to get straight is that this is how i want you to constrain my route for you for me right so then from after defining it i'll come to my uh my routes where the magic is happening and then i have to require my constraint so i have to require my constraint which is the name uh submarine yeah some domain right now this this is where uh it gets better because because i've been able to define my constraint now i can use it so all i have to do is just use the keyword constraint which is the rails keyword for constrain and then i'll call the class i defined some domain required and then i will just wrap it in this yeah so it means that as long as you are within i hope i define my class right normally that's the yeah so what i'm saying that uh constrained all right routes that matches this request so as long as whatever resource i'm looking for is within this request i want you to show me these links yeah so um but the downside of this approach is also that you have to make sure that your resources are underneath the constraint first so that in case it has to pick in case it ha some account has to be picked first it will not overwrite it so if there is account here before the constraint that account will be called first but what i'm interested is i want to make sure that my some domain fails before you can call any other guy within the uh the how do we call it any other guy within the sub domain i don't know if i'm making sense yeah yeah yeah are making sense yes okay okay so now that i have done it this way then all that is left for me to do now [Music] i hope i will define it right okay so now that i have finally this way and i can find the account by the sub domain right that is all that is that is all that is necessary for me to do right now but because i have scoped the the post right i also have to scope it in my views please don't make sense because i have scoped uh puts controller within the uh the account so i have to also create a folder post yeah so in this way i have been able to constrain it so that i can call the person out i don't have to be able i don't have to necessarily be calling uh the i don't have to unless you would be calling it whenever so now we can restart my server let me let me remove everything again and then set it up what yeah something in the roots [Music] might work okay so i think this is what she does okay i already use frogs [Music] oh okay yeah i i think um because i scope i have to uh in a way do um before this one is calling it's calling everyone right so one of the things to uh when i when i did this because the post is already here and the account is already here i have to segregate each account by its uh particular resource so here i can define as account route and see i think yeah because i have to be specific which of the routes i'm trying to use because i have roots here i have roots within the constraint but i can't find any i can't find so rails is saying that okay you are defining two routes in your race route but you have to define which one am i supposed to use am i supposed to use the routes if they're posting this or am i supposed to use the route with that count index but what i'm interested that whenever you encounter this one i want you to use this at the root of my account yeah so now when i go to my yeah so now that i have my uh my now you can see that i'm in the home page of my sub domain but the post is still here because i define it to be within the constraint and i don't need to necessarily go to if i had not done this if i not done it this way what would have happened is that whenever i go to my uh roots controller uh my posts controller and whenever i create a route i have to direct it to the sub domain where i want to go which is not redirect to root sub domain where i have to go but because i define my routes and then my constraints this way i don't necessarily have to be worried about the the specific uh route so here if you can observe i am within my accounts uh my accounts right so i can just create a post a moment so here and then i'll post now you see that it's trying to go to this and by now it's telling me that the accounts must be present right yes it's it makes sense because it needs the account in order to go and then do it so because i've already defined my current account i don't have to worry about it because all i have to do is just uh go to uh my post my post and then call the current account right fantastic and then from then here i can then use the uh post params right because i've already defined it already i've already defined it and i'm in my current account right so now functional sometimes resetting helps ah because i've got nothing to lose yet yeah so yeah i can come in so now i can create my new account now my new account is created and within the sub domain so i can create the test posts what are we not doing right um okay we've defined the relationships in account rb and poster b and it must be something here i would definitely call in the current account method in the new [Music] try to display the current account in the view just to see if we have it that's fine uh so in the new view in the post new view just call a current account oh yes yes yes um yeah so uh so we made a mistake okay so i think we are we have scoped the post to the account right but then we right we have yeah we have closed the scope to account so we have to call accounts right because we we have scoped it to uh we are saying it is scoped to the account but what we are trying to we are defining the post within the subdomain but we are not calling the account where it should be scoped too right because we haven't defined inheritance i hope i'm right we are about to know uh no uh and what do the logs say okay it looks like in the logs it didn't pass there it didn't pass the account id yeah yes he didn't pass the account yes [Music] um well it's either the post controller yes uh i think oh okay so i think we are making a mistake right because uh the problem might be coming from the resources both yes we have not defined our resources within the post yeah so it brings us to the regular yeah yes yes yes it brings out there and then he's not finding the account that's opposed but we want to we want you to be within the um the because of the constraint we defined it is because it didn't find a constraint i think it was going through the the second uh resources that we declare right yeah let's see if this one works i like that okay yeah so the form the problem is maybe the other form you have it open [Music] further yeah uh accounts posts form try to open it yeah this one this one post oh yeah maybe it should not accounts but account uh account okay okay let's try no not much to lose [Music] i yeah this is how i can cut that the name of the module we used i'm coming let's see okay yeah yeah so it was the because because we we um i think what happened was that we're already we have defined us we have defined the scope but the scope is not a name space it's actually a race constraint so we this this one would have worked if i had defined in my route that this one is a namespace if it was let's say uh namespace uh maybe accounts right then the route defined then that would have makes sense because i have to first locate the name space where i am before i can go to the resource but you are not asking me to do that what you are telling me to do here is that i just have to look for uh a sub domain required once i get a sub domain reply nothing else matters so you don't need to uh define uh my uh you don't need to define this one over here because i don't need it you are not scoping to a namespace so i hope i'm making sense absolutely yeah i'm not going to a namespace so this one wouldn't matter so then now we can now create our uh we can now create uh so now we can know that whatever we create is within the subdomain where we are right now so let's see if we are not lying to ourselves let's go to our console and see if uh yes so that this thing we declared is the post we declared is there yeah the current account yes yes it's within is within that so we can then so we can actually even come to now we can move from our sub domain um yeah and then create another account right yes now we are within your sub domain right so well uh we didn't add the any validation not to display posts uh across sub domains yeah yeah yes so what what we did was that we are displaying all the posts within the uh resources right so yeah we have to yeah current account of both yes now we are within your scope now so yeah i think yes yes so i think now it's it's settled etc now so which means that we can go to all the accounts as well yeah now you have all the accounts and we know that so here now you can see that it is moving to another one you know so here we have to make sure that on our index page we have to declare where we have the other accounts right so in the what is the account index page right we have to change the routes right yeah so we have to change that route so we have to go to root url right and then sub domain account will both sub domain yeah ah current account do we have a current account at the moment i think so the main equals account dot sub domain we don't have uh the current account helper at the moment yeah we do know using speeding yes yes so i think once we do it this way we can then see now you can see that the url has stayed at the bottom of my page yeah so now we can go to the respective sub domain and then create our staff there yeah so basically that is that so the idea is just first uh adding a sub domain to your account and then making sure that you decry you declare your sub domain constraints so that whenever the url request to the subdomain and the subdomain is not directly point to www you use your uh route constraint here so here you can define all your resources within then again the downside is always that you have to make sure that you are calling the current account dot the whatever resource you have defined within yes so that is it for uh um the the sub domain so this is how i uh this is how i went about implementing my sub domain i hope i looked fantastic yeah so the second challenge would be to push into production and make it work in production yes okay so now the challenge in production is that uh the production the production way you know that uh hiroku does not accept um wild card right goku does not produce xsl for world cups so what you have to do is that i actually use uh cloudflare and then let's encrypt so i use cloudframe cloudflare and then less encrypt right so um cloudflow automatically gives you the opportunity to have a xsl i mean by default right but before you can also get the xsl for your start domain you have to be in one of their page page tier right and luckily for us when we spoke that i introduced the less encrypt uh less encrypt uh approach to me so let's encrypt has a way where you can actually add your you can actually generate xsl for your subdomain so it is actually a script i've i found online i've forgotten the post but it was this post where you have to use less encrypts on your app so let me just show you the script i run rather yeah so um so if you are using a stamp domain right this is the script you have to run so so first you have to uh install set bot on your machine then you have to run uh so first you have to uh define which kind of challenge your uh search your certificate the certificate of xsl you are using is defined and then you tell the server that you want to use less encrypts api server and then the directory to use then from there you tell them what domain you want to use so here i told him that i want to use my word card dot patriot.com which means wherever you go you have to use that right so uh let me just uh for illustration sake let me just copy this [Music] and then paste it here and then i will use my it's uh a password to what exactly a password to your terminal like to your uh to your terminal yes so you see once your password is correct it will tell you that uh you have to paste this in whatever dns you are using okay so here in this case i'm using cloudflare right so i'll just copy this one go to uh cloudflare here and then add it to the text here i have to choose the text one the tst and then i'll paste in my link here and then i'll come back and paste the value over here as well so i'll paste my value here and then i'll save it so it means that what i'm saying now now what i'm telling cloudflare is that as long as i'm on a sub domain i want the ssl certificate to be issued by less encrypt yeah once you see it then you just save it right then once you save it you have to tell heroku that you want your uh you want your sub domains to be protected by xsl so you want to give them a certificate right and how you do that is so if you want heroku to give to you i don't know the machine you are using but i think it's pretty much uh the same so now this is how you tell heroku so when once you finish once uh cloudflare accepts your um access your lesson creates and certificate they'll give you two files this one they'll tell you where they have saved your certificate let's encourage to tell you exactly why they have stayed so here online texting here on my tech and they tell me that this is where my first certificate if i want to go live yes right so if i want to use the certificate all i have to do is just to tell heroku that heroku i'm using certificate i want you to add this to the certificate go to where this file is followed by the second file which is my private so you can see that i have two keys here 19 i have the full life full change screen and then online 16 i have the private key as well yeah so here what i'm telling you real quick is that heroic i'm adding a new set of certificates but i want you to find a certificate from this file as long also from this file you can choose to do it individually you can actually do it one after the other so you can say hiroku add the first one and then add the second one it's also accepted yes once you do this whenever you point to a sub domain let's encrypt will automatically pick the uh who add the xsl to it for you but then uh-huh yeah okay so once again to clearly understand uh where are these let's encrypt the certificates held at the moment before i run the commander to add them to heroku oh okay so when so you know the steps we followed right where we copied everything here right yeah so once you finish they'll give you uh less enclaves will tell you congratulations your certificate and chain have been saved at this is the first is on your machine so i think the machine depending on the yes so depending on the what machine you are using whether liners windows or mac it will tell you where the file has been saved so here it is telling me that if i want to look at my chain it is located in etc let's encrypt folder live folder they created the url i created here for them for my so they created the folder for the url as well and then added the food chain so this is the first certificate for the food chain and then the other they also created a certificate for me with the private key so your key file has also been saved at uh let's and create folder and they so they they say they give you two files both they tell you the location where they have saved it so all that you are telling heroku is that it should go on your computer where those files are saved and then you just copy it but again you can decide to go to the directory and copy it and post it in the place where it's easily accessible so maybe you can post it on your desktop or however and then just just fetch it from wherever it is located but i found less encrypts for that creation quite okay so i just used it that way so that's about it right yes yes basically that's about it but then uh for heroku at least you have to make sure that you you are on the page you are on the page here before you can use xsl i found it the hard way i had this app and i i didn't i was on the appreciate so you need to have you need to be at least on the basic tier before you can use any kind of specifications and uh do you need to manually refresh the certificates from time to time oh no okay yes yes so let's encrypt uh gives you the certificate for three months so every three months you have to repeat this process but i think i was reading a few days ago that they want to extend it to six months but i'm not sure but so far it is only last for three months but when your three months is about to expire i think about a week or so lesson grateful send you an email to remind you that your certificate is expiring so uh you should uh go about it like you should find a way to uh renew it yeah yeah i'm just looking forward to repeating it and replicating it as fast as possible yeah yeah yeah it's it's it's pretty awesome it's pretty awesome so that is it for the sub domain uh declaration but the key point that i want to drive home is that one you need to make sure that your account has a sub domain and then you have to also ensure that you have defined your constraint very well i think the bread and butter of it all is this constraint so that rails will route every place that's not directly followed with www to link to your sub domain and then you have to make sure that in your you have to make sure that in your route file you define the constraint as well so that uh whatever you scope will be within uh that space yes yeah great yes basically that so we with this one the beauty is that we don't have to necessarily always be defining our route because here we can just go to this place and then we can go outside the subdomain and declare a post so maybe if you have users that you want them to declare certain kind of post or something you can give them that option and then maybe the users who are on your app and are playing or something you have to give them each of the sub domain okay and it would be great if you saved it as a git repo and uh possibly also those commands that need to be run for let's encrypt and for heruku and uh i'm really looking forward to trying to replicate it yeah sure that's that's pretty much oh that's pretty much
Info
Channel: SupeRails
Views: 622
Rating: undefined out of 5
Keywords: ruby, rails, ruby on rails, tutorial, programming
Id: 4hwVvg2XdtQ
Channel Id: undefined
Length: 55min 23sec (3323 seconds)
Published: Fri Sep 24 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.