00:07
stems from our organization and relates to it in some way. Now, despite us having just written out our entire models, let's refactor them a little bit to extract out some of that repetitiveness of attaching
00:17
our organization to each of those individual models that we have. We're going to be doing that using something called mixins. So within our app models directory,
00:25
let's go ahead and right-click on that and hit New File. Now, to keep our mixins separate from our other models, let's put these inside of a folder called mixins,
00:32
and we'll call this file with underscore organization.yes. Our underlying goal with this mixin is to have a class,
00:40
but we can call this just our mixin class to give it a name. The name doesn't really serve us much of a purpose here. We ultimately want this to extend our base model.
00:49
I'm going to go ahead and hide our sidebar away here momentarily and drag our course model over to the right-hand side so that we have them side-by-side here. What we want to do is extract out the column definition out of
00:59
our course and instead house it inside of our mixin. In addition to that, it would also be great to do that with the relationship definition as well so that they're side-by-side in one central location.
01:09
So this is our end goal is to have this mixin class apply onto our course and have the organization ID and its relationship
01:17
bind into our course just via applying this mixin to the course class. Currently, to apply this mixin into our course though,
01:25
we would need to switch from extending our base model to instead extending our mixin class coming from our width organization file. But let's say that we were then to extract
01:34
the same behavior out into a width access level and a width difficulty, then it would become hard to apply all three, four, or however many of them we have into
01:44
our course class without creating an extension chain, applying each and every single one of those individual combinations of those that we would then need. That's where the mixins come into play.
01:52
They allow us to bind partial classes together to form one ultimate base that we'll extend off of. It just allows us to take apart from here,
02:02
apart from there, and mush it all together so that we can extend off of it. So in order to do that, we need to wrap our mixin class inside of a function.
02:11
So we'll export const and we'll call this function with organization as we'll be using it to apply in our organization ID and relationship.
02:20
This function will accept in a class of its own. These are the classes that will then be composing or mixing
02:27
together to form our final base that we'll extend off of. So we'll call this superclass and we need a type to apply to this.
02:35
For that type, that's where we're going to want to reach for a generic. So we'll call this T and we ultimately wanted to extend our base model.
02:43
Now, there is a TypeScript issue with the base model approach that we have right here. Essentially, TypeScript is going to expect the arguments of
02:50
the constructor to be a specific value and that's just not going to be the case for us. So AdonisJS has provided a way to circumvent that via a normalization constructor. Before we apply that though,
03:00
let's go ahead and just move our courses panel over a little bit here to the side so that we can just see the columns still and then apply
03:06
our generic as the type of our superclass and get our arrow function here finished out. So hit enter there and then move that and curly brace down to the end of our file. Now, for that normalization constructor,
03:16
we're going to want to import it. So normalization constructor from AdonisJS core types helpers. Then we're going to want to wrap our base model in it.
03:24
So normalization constructor and provide the type of our base model into it just like so. Let's also go ahead and come down to our column, belongs to or one of those,
03:34
hit command dot on it and import all missing imports. Then we need to switch our belongs to to a type of import. So hit command dot on that and use type import there.
03:43
At this point, our red squiggly should all just be linter base. We can give it a save and there we go. Now, we need to make use of our superclass in the place of our base model.
03:53
As the superclass ultimately extends our base model, but it could be another mixin, could be the base model itself or what have you.
04:01
So it's just a generic version of our base model. So we can extend our superclass there.
04:07
Then lastly, we want to return our mixin class from this mixin function.
04:13
Now, let's pause here for a second because how you define your class here can cause issues. Since class doesn't necessarily need a name,
04:20
you may say, okay, but why can't I just return class extends superclass? You'll notice that with this, we have red squigglies on our decorators.
04:29
That's because decorators are not valid with this particular approach. For some reason, TypeScript just does not recognize them whenever you don't give your class a name.
04:37
So that is why we are not returning right there and instead giving our class a name and returning it after we've defined the class. With our class defined this way,
04:46
TypeScript will pick up and be able to use our decorators here. Let's go and bring our course back over. We can get rid of our unused organization import.
04:54
Let's wrap our base model in Adonis Chayes' compose method. This is a helper function that just helps us apply these mixins in a more clean fashion.
05:04
We get a red squiggly here because it expects at least two arguments. We pass in as the arguments, each one of the classes that we want to compose together
05:13
to ultimately extend our course class with. So here we want to add in our base model as well as our with organization mixin.
05:21
And with that applied, our course now has an organization ID column on it, as well as an organization relationship. And we can verify that by going down to the end of our file,
05:30
doing const course equals new course. And we'll be able to see course.organization and organization ID,
05:38
as well as if we do related, we'll see within here that we have an organization relationship that we're then able to work with. Awesome.
05:46
So let's go ahead and apply this to all of our other models that have an organization ID on it. So we go ahead and save our mixin and close that out. We're now done with it.
05:55
And let's open up our Explorer panel again. We'll just start at the top and work our way down.
06:00
Our access level here, go ahead and compose base model with organization. And then we're able to go ahead and get rid of our organization ID column,
06:09
scroll down and get rid of the organization relationship as well. And then of course, don't forget to clean up your imports too. Okay, let's do that now with our difficulty next.
06:18
So wrap our base model in a compose method and then apply in our with organization mixin, get rid of the organization ID as well as the relationship, scroll back up.
06:28
And as opposed to removing our unused imports manually, we can also hit command ship P and search for remove unused imports. And just hit enter on that and it will do it automatically.
06:38
Okay, our email history is going to relate back to the user, not the organization. Our lesson looks like that has an organization on it.
06:45
So we will compose base model with organization, get rid of the organization ID and the relationship,
06:53
command shift P, remove unused imports, and we're good to go. Now our module, compose with organization,
07:00
get rid of the ID, relationship, remove unused imports. Our organization invite, yep, that's got it there as well. So we can do that here too.
07:09
Compose with organization, remove that, and relationship and our unused imports. Our organization is not going to relate to itself.
07:18
Password reset goes to the user. Role, I don't believe, nope, does not. Status does though. So we can compose there as well.
07:26
And then with organization, the ID as well as the relationship. Now our user is a different story because this doesn't have an organization ID column on it.
07:36
Instead, it relates to the organization via a many-to-many relationship. So this one, we do want to leave this relationship on the user model itself
07:45
because our mixin explicitly expects belongs to, where the organization ID is on the model and the class that we're extending this with belongs to the organization.
07:54
So we are all set now. We've now replaced all of the specific organization applications that we have across our models
08:02
to instead compose in our with organization mixin. Now, if you want to, you can also do that with your access level, difficulty, and status as well
08:11
because those are applied on multiple models too. And if you were to do that, you would just compose them in so you could do something like with access level
08:20
and it would get applied just the same. We're not going to do that here. I felt like the organization was a pretty good demonstration itself. So we will stop with just that.