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, 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
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
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
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, 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,
inValid, same thing.
Alright. So that’s the end of the file. Now let’s go back to where our
updatedState are. So
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
Let’s go ahead and find the
dirtyState and see what’s there. So it’s
defined up here, and the
uncommitted, and so that goes for both the
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
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.
saved whereas for the
saved is up a level under
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.
- Ember Data 2.0-Getting Started, and Basics of DS.Model
- Ember Data 2.0-Getting Data from the Server with findRecord and findAll
- Ember Data 2.0-Store Manipulation with Peek, Unload, and More
- Ember Data 2.0-Create, Save, and Destroy Records
- Ember Data 2.0-Updating Data, Tracking Changes, and Rolling Them Back
- Ember Data 2.0-Metaprogramming with DS.Model Attributes Property
- Ember Data 2.0-Model States and Flags
- Ember Data 2.0-states.js Deep Dive
- Ember Data 2.0-Relationships
- Ember Data 2.0-Metaprogramming with Relationships
- Ember Data 2.0-Overview of using Adapters and Serializers
- Ember Data 2.0-Overview of Customizing Adapters and Serializers
- Ember Data 2.0-Essential Adapter Customizations
- Ember Data 2.0-Advanced Adapter Customizations
- Ember Data 2.0-Miscellaneous Adapter Customizations
- RESTAdapter vs JSONAPIAdapter vs ActiveModelAdapter
- Introduction to Serializers
- JSON API
- Serializers-How are normalize and normalizeResponse different?
- Serializers-Extracting Attributes and IDs
- Serializers-Extracting Relationships
- Serializers-keyForAttribute and keyForRelationship