Series: Introduction to Ember Data 2.0

Ember Data 2.0-states.js Deep Dive

Published on Dec 26, 2015

We’re diving deep into the system/models/states.js file from the Ember Data source code. I’ll walk you through it, pointing out the highlights, showing how I got the information for the Model State Explorer, and going more into depth than I did last episode.

Something to note that I forgot to mention in the video: these nested hashes inherit properties from the parent hash, including flags and methods (presumably through an extra processing step somewhere, since hashes don’t normally inherit like that).




Last episode, I introduced the Ember Data Model State Explorer, which helps you explore different states within the Ember Data Model and the different flags that you can have on each.

Today, we’re going to dig deeper into the source code in states.js, and this is where I got all the information to create the model explorer. So I’ll go over the general structure of the states file. Let’s get started.

So most of the data in states.js is based on these hashes. So the RootState is one of the hashes. It contains most of the other hashes. And it starts off by having all the flags as false, except isValid which is true.

Then below this we get our first event definition. Here it’s a default event which is just a plain function. And then underneath that we have a definition of unloadRecord. Remember, unloadRecord, it’s not an event. It’s a method that you can call on a model.

So this is a default one and you can see that it is redefined in several other states. So based off that, you can see that in different states, calling the same method may do different things, even though generally it’ll look the same to a user because it’ll be a bad API if it didn’t.

Alright, so inside this default unloadRecord, you’ll notice that we have our first transitionTo. And remember that’s a private method, and we’re transitioning to deleted.saved.

Alright, so the default is if you unloadRecord, that’s a state it goes to.

Alright, so we scroll down and we’re getting to some SUBSTATES. Here’s the empty substate. That is one without any child states, and the big difference is the isEmpty is true, the flag is true, and then it has some other events defined. These events of course typically include a transitionTo as well as some other work that they do.

Alright, we scroll down, and we have the loading state, and it’ll set the isLoading flag to true, and then it’ll once again, it will define some more events, and then it defines the exit method which is presumably used when you’re exiting the loadingState.

Now we’ll scroll down and here where things are getting more interesting because we have loaded, and then it has even more nested stuff, like saved. And we have an additional property called initialState, and here it’s saved, so if you transition to loaded, then it’s actually transitioning to loaded.saved. I think that’s how that works.

And so another fun thing about reading source code is that you get to know what things people aren’t sure about, and this is definitely not in the docs.

Alright, so when we’re getting to save, saved which is a subset of loaded, so we’re in root.loaded.saved now, and it looks like we’ve got some setup to do and then of course defining events, a lot more here than there were in the last few.

Alright, and here it gets a little bit more interesting because we have the createdState and updatedState, and those are created elsewhere. So remember that these are created elsewhere. We’re going to come back to those.

First we’re going to go through deleted. So deleted, a lot of it is the same story. You’ll notice that we have the dirtyType as well, we mentioned that in the last episode, and its initial state is uncommitted. And so we set certain flags, it goes to uncommitted, it sets up more events, and inFlight once again sets up flags, sets up events, saved, inValid, same thing.

Alright. So that’s the end of the file. Now let’s go back to where our createdState and updatedState are. So createdState and updatedState are both built off something called dirtyState, and they have a few differences. One of the big ones is their dirtyType, as well as a few extra things that are changed. It looks like these are events that are changed.

Let’s go ahead and find the dirtyState and see what’s there. So it’s defined up here, and the initialState is uncommitted, and so that goes for both the created and updated substates within loaded. This is a very similar story to what we had before. We’re setting flags and then we’re setting events.

And a lot of this is really similar to what we saw in deleted and its substates, and I guess the reason why they didn’t do dirtyState for deleted as well is because these go to committed by default and deleted goes to saved, and these saved is coming off of unloaded, not off of... Here, I’ll show you. deleted has saved whereas for the loaded created and loaded updated, saved is up a level under loaded.

And so that is our deep dive into states.js. So you can see we’re getting back to the RootState here. I hope you enjoyed it and I hope it makes you more confident in digging into the source code as well as understanding the states and flags in Ember Data Models.

Introduction to Ember Data 2.0

Subscribe to our mailing list