WEBVTT

1
00:00:00.080 --> 00:00:02.439
<v Speaker 1>Welcome back to the deep died curious minds. You know

2
00:00:02.520 --> 00:00:05.080
<v Speaker 1>that feeling you've got this really powerful tool, maybe like

3
00:00:05.599 --> 00:00:08.919
<v Speaker 1>a brand new engine, but your current setup, your infrastructure,

4
00:00:09.080 --> 00:00:11.039
<v Speaker 1>maybe uses a slightly different kind of fuel. It doesn't

5
00:00:11.119 --> 00:00:14.800
<v Speaker 1>quite mesh. Well, today we're tackling exactly that kind of challenge.

6
00:00:15.119 --> 00:00:18.120
<v Speaker 1>But in the world of web development, specifically with mber Data.

7
00:00:18.480 --> 00:00:22.440
<v Speaker 1>It's the data layer for mber dotjs apps and well,

8
00:00:22.480 --> 00:00:25.519
<v Speaker 1>it's designed to make interacting with APIs and managing your

9
00:00:25.559 --> 00:00:28.960
<v Speaker 1>data really smooth, supercharge that user experience, you know. But

10
00:00:29.000 --> 00:00:32.880
<v Speaker 1>here's the kicker. What if your API isn't shall we

11
00:00:32.920 --> 00:00:36.479
<v Speaker 1>say standard, What if it uses different naming or weird

12
00:00:36.679 --> 00:00:39.439
<v Speaker 1>URL structures or throws errors you don't expect. That's what

13
00:00:39.479 --> 00:00:42.280
<v Speaker 1>we're digging into today. How mber data is a really

14
00:00:42.320 --> 00:00:44.960
<v Speaker 1>smart design actually lets you adapt to any API out there.

15
00:00:45.240 --> 00:00:48.039
<v Speaker 1>Think of it like getting a universal translator. Yeah, making

16
00:00:48.039 --> 00:00:49.960
<v Speaker 1>your app and your back end speak the same language,

17
00:00:50.000 --> 00:00:52.000
<v Speaker 1>no matter how quirky that back end might be.

18
00:00:52.359 --> 00:00:54.920
<v Speaker 2>Exactly that's a challenge a lot of developers face, right,

19
00:00:55.000 --> 00:00:59.200
<v Speaker 2>integrating a really robust front end like ember data with

20
00:00:59.520 --> 00:01:03.000
<v Speaker 2>an excus sting back end API that might be well,

21
00:01:03.079 --> 00:01:06.519
<v Speaker 2>let's call it unique. Ember Data definitely has its own

22
00:01:06.519 --> 00:01:10.200
<v Speaker 2>opinionated way of doing things, it's preferred conventions. But its

23
00:01:10.239 --> 00:01:13.159
<v Speaker 2>real power, I think, is in how extensible it is.

24
00:01:13.480 --> 00:01:15.400
<v Speaker 2>We're going to look at its core parts, the store,

25
00:01:15.519 --> 00:01:19.239
<v Speaker 2>the adapters, and the serializers and see how understanding those

26
00:01:19.319 --> 00:01:22.359
<v Speaker 2>lets you connect to pretty much any data source. It

27
00:01:22.400 --> 00:01:25.159
<v Speaker 2>really saves you from reinventing the wheel for common stuff

28
00:01:25.200 --> 00:01:27.959
<v Speaker 2>like identity mapping or managing relationships.

29
00:01:27.959 --> 00:01:30.599
<v Speaker 3>Okay, let's unpack that. An analogy might help imagine. Your app.

30
00:01:30.680 --> 00:01:33.760
<v Speaker 3>Is this like bustling city and all your data users

31
00:01:33.840 --> 00:01:37.480
<v Speaker 3>products whatever they're the citizens moving around. Mber Data is

32
00:01:37.480 --> 00:01:40.200
<v Speaker 3>like the city management system, keeping track of everything, and

33
00:01:40.239 --> 00:01:42.959
<v Speaker 3>at its heart there are these three key departments running

34
00:01:42.959 --> 00:01:45.319
<v Speaker 3>the show. First up, you mentioned the store. What's that

35
00:01:45.560 --> 00:01:46.280
<v Speaker 3>like city hall?

36
00:01:46.680 --> 00:01:48.599
<v Speaker 2>Sort of? Yeah, think of the store as the city's

37
00:01:48.640 --> 00:01:51.599
<v Speaker 2>central records office, but also like a super fast memory bank.

38
00:01:51.840 --> 00:01:54.480
<v Speaker 2>When your application needs some data, it doesn't go straight

39
00:01:54.480 --> 00:01:56.640
<v Speaker 2>to the API. It asks the store first.

40
00:01:57.040 --> 00:01:59.599
<v Speaker 3>Ah, so it checks its cap precisely, and when data

41
00:01:59.599 --> 00:02:03.200
<v Speaker 3>comes in, the store caches it intelligently. But it's more

42
00:02:03.239 --> 00:02:06.120
<v Speaker 3>than just a simple cash The really clever part is

43
00:02:06.159 --> 00:02:09.599
<v Speaker 3>the identity map. This prevents you from having say two

44
00:02:09.680 --> 00:02:13.400
<v Speaker 3>different JavaScript objects representing the exact same user record and memory.

45
00:02:13.439 --> 00:02:16.560
<v Speaker 3>How does that work? Well, imagine you fetch a list

46
00:02:16.560 --> 00:02:19.919
<v Speaker 3>of contacts, maybe GD contacts, and later you fetch a

47
00:02:19.919 --> 00:02:24.039
<v Speaker 3>specific one GD contacts one. If contact one was in

48
00:02:24.039 --> 00:02:27.199
<v Speaker 3>both responses, the store ensures you only ever have one

49
00:02:27.400 --> 00:02:31.680
<v Speaker 3>object instance for that contact with EED one. It preserves

50
00:02:31.680 --> 00:02:32.800
<v Speaker 3>that object identity.

51
00:02:33.080 --> 00:02:36.240
<v Speaker 2>Okay, I see, so no confusing duplicates floating around. That

52
00:02:36.360 --> 00:02:39.840
<v Speaker 2>sounds vital for keeping things consistent, especially in complex apps.

53
00:02:39.879 --> 00:02:44.240
<v Speaker 3>Absolutely crucial for scalability and uh just general sanity. Really.

54
00:02:44.520 --> 00:02:47.520
<v Speaker 2>So, the store holds the records, keeps them unique. But

55
00:02:47.680 --> 00:02:50.439
<v Speaker 2>how does it actually, you know, talk to the outside world,

56
00:02:50.639 --> 00:02:52.479
<v Speaker 2>to our potentially quirky API.

57
00:02:52.639 --> 00:02:55.719
<v Speaker 3>Right, The store doesn't talk directly. It delegates. That's the

58
00:02:55.800 --> 00:02:56.599
<v Speaker 3>job of the adapter.

59
00:02:56.759 --> 00:02:58.919
<v Speaker 2>The adapter. Okay, so if the store City Hall, the

60
00:02:58.960 --> 00:03:02.719
<v Speaker 2>adapter is the Department of Foreign Affairs. Huh yeah, that's

61
00:03:02.719 --> 00:03:04.639
<v Speaker 2>a good way to put it. The adapter handles how

62
00:03:04.639 --> 00:03:08.159
<v Speaker 2>to communicate with external data sources your API. Its job

63
00:03:08.240 --> 00:03:10.520
<v Speaker 2>is to figure out the full URL for a request,

64
00:03:10.919 --> 00:03:15.560
<v Speaker 2>actually make the HTTP call using ajax, fetch maybe even

65
00:03:15.599 --> 00:03:18.319
<v Speaker 2>web sockets, and it can even talk to things that

66
00:03:18.360 --> 00:03:21.800
<v Speaker 2>aren't remote APIs like the browser's local storage or index

67
00:03:21.879 --> 00:03:25.319
<v Speaker 2>dB possible very and the key thing is this separation.

68
00:03:25.599 --> 00:03:29.319
<v Speaker 2>If your API changes how it expects requests, maybe moves

69
00:03:29.360 --> 00:03:32.479
<v Speaker 2>from rest to grah ql, or just changes its URL scheme,

70
00:03:32.919 --> 00:03:36.199
<v Speaker 2>often you only need to update the adapter, not rewrite

71
00:03:36.360 --> 00:03:40.560
<v Speaker 2>huge chunks of your application logic decoupling nice exactly. Ember

72
00:03:40.680 --> 00:03:43.520
<v Speaker 2>Data ships with a few standard ones REST adapter for

73
00:03:43.520 --> 00:03:46.240
<v Speaker 2>common rest stuff JSON APA adapter, which is the default

74
00:03:46.240 --> 00:03:48.759
<v Speaker 2>and follows the Jason Dot API spec and there used

75
00:03:48.759 --> 00:03:51.280
<v Speaker 2>to be an active model adapter for rails though that's

76
00:03:51.280 --> 00:03:51.919
<v Speaker 2>an add on now.

77
00:03:51.960 --> 00:03:54.759
<v Speaker 3>Okay, So the adaptor handles the where and how of

78
00:03:54.800 --> 00:03:58.000
<v Speaker 3>the request the transport layer basically, But what about the

79
00:03:58.000 --> 00:04:00.439
<v Speaker 3>actual data the payload? What if the app I sends

80
00:04:00.479 --> 00:04:03.199
<v Speaker 3>back data that looks completely different from what mber data expects,

81
00:04:03.479 --> 00:04:05.280
<v Speaker 3>different grammar, different vocabulary.

82
00:04:05.360 --> 00:04:07.479
<v Speaker 2>That, my friend, is where the serializer steps in.

83
00:04:07.840 --> 00:04:10.319
<v Speaker 3>The serializer the linguist.

84
00:04:09.960 --> 00:04:13.639
<v Speaker 2>Precisely, The serializer is your data's translator. It has two

85
00:04:13.680 --> 00:04:18.800
<v Speaker 2>main jobs. First, serialization, taking data from your Mber app

86
00:04:18.879 --> 00:04:23.279
<v Speaker 2>and formatting it correctly to send to the server. Second, normalization,

87
00:04:24.160 --> 00:04:27.240
<v Speaker 2>taking the raw data received from the server and translating

88
00:04:27.240 --> 00:04:30.000
<v Speaker 2>it into a structure. Mber Data understands, so.

89
00:04:30.040 --> 00:04:34.000
<v Speaker 3>Adapter handles the connection. Serializer handles the language you got it.

90
00:04:34.399 --> 00:04:38.079
<v Speaker 2>That separation is fundamental to ember Data's adaptability. It lets

91
00:04:38.120 --> 00:04:39.920
<v Speaker 2>you tackle the how to talk and the what to

92
00:04:40.000 --> 00:04:41.600
<v Speaker 2>say independently and.

93
00:04:41.560 --> 00:04:45.040
<v Speaker 3>I'm guessing just like adapters, there are different serializers for

94
00:04:45.079 --> 00:04:46.240
<v Speaker 3>different API languages.

95
00:04:46.399 --> 00:04:48.680
<v Speaker 2>Spot on, mber Data gives you three main ones out

96
00:04:48.720 --> 00:04:52.000
<v Speaker 2>of the box. There's the basic Jason serializer for simple

97
00:04:52.040 --> 00:04:55.759
<v Speaker 2>flat Jason good starting points sometimes, and the rest serializer.

98
00:04:56.079 --> 00:04:59.199
<v Speaker 2>This one expects data wrapped in a root key like contact,

99
00:04:59.480 --> 00:05:01.639
<v Speaker 2>and it also understands how to handle sideloading.

100
00:05:01.759 --> 00:05:02.560
<v Speaker 3>Sideloading what's that?

101
00:05:02.879 --> 00:05:06.079
<v Speaker 2>Oh, that's when an API includes related data in the

102
00:05:06.120 --> 00:05:09.560
<v Speaker 2>same response to save extra network requests like getting a

103
00:05:09.600 --> 00:05:12.199
<v Speaker 2>contact and their company details all at once. The rest

104
00:05:12.240 --> 00:05:13.720
<v Speaker 2>serializer can unpack.

105
00:05:13.399 --> 00:05:16.240
<v Speaker 3>That gotcha, reduces chattiness exactly.

106
00:05:16.759 --> 00:05:19.920
<v Speaker 2>And finally, there's the Jason up a serializer, which is

107
00:05:19.920 --> 00:05:24.240
<v Speaker 2>built specifically for APIs that strictly follow the official Jason

108
00:05:24.279 --> 00:05:27.839
<v Speaker 2>dot API specification. That's often the default. The idea is

109
00:05:28.079 --> 00:05:30.920
<v Speaker 2>you pick the built in serializer that's closest to what

110
00:05:30.959 --> 00:05:33.759
<v Speaker 2>your API does, and that minimizes the custom transation work

111
00:05:33.800 --> 00:05:34.800
<v Speaker 2>you need to do initially.

112
00:05:35.000 --> 00:05:38.040
<v Speaker 3>Okay, this is where it gets really practical for you listening,

113
00:05:38.120 --> 00:05:41.240
<v Speaker 3>because let's face it, real world APIs aren't always textbook

114
00:05:41.240 --> 00:05:45.439
<v Speaker 3>perfect are they? Rarely ember data anticipates this. That's why

115
00:05:45.480 --> 00:05:48.560
<v Speaker 3>these customization hooks exist. It's about making your app talk

116
00:05:48.639 --> 00:05:51.879
<v Speaker 3>smoothly to your specific back end warts and all. Let's

117
00:05:51.879 --> 00:05:56.160
<v Speaker 3>start with customizing adapters. Say my API uses singular nouns

118
00:05:56.160 --> 00:05:59.519
<v Speaker 3>for URLs like contact one instead of contacts one. How

119
00:05:59.519 --> 00:06:00.639
<v Speaker 3>do I tell data?

120
00:06:00.720 --> 00:06:02.879
<v Speaker 2>Yeah, that's a common one. It's surprisingly easy. You just

121
00:06:02.920 --> 00:06:05.439
<v Speaker 2>override a method called pathsfotype in the adapter for that

122
00:06:05.480 --> 00:06:08.720
<v Speaker 2>specific model. So in your app adapters contact dot js file,

123
00:06:08.759 --> 00:06:11.160
<v Speaker 2>you'd add a path four type model name function and

124
00:06:11.279 --> 00:06:14.759
<v Speaker 2>just make it return the singular model name. Done. Simple enough,

125
00:06:15.040 --> 00:06:17.240
<v Speaker 2>so that handles the base path. But what if I

126
00:06:17.279 --> 00:06:20.839
<v Speaker 2>need a totally custom URL structure for a specific query,

127
00:06:21.319 --> 00:06:24.519
<v Speaker 2>like searching contacts by city, but the API wants app

128
00:06:24.600 --> 00:06:27.319
<v Speaker 2>contacts by city Los Angeles instead of a query peram

129
00:06:27.360 --> 00:06:28.680
<v Speaker 2>like dot city los Angeles.

130
00:06:28.800 --> 00:06:32.680
<v Speaker 3>Right, for specific query logic, you'd override are all four query. Again,

131
00:06:32.759 --> 00:06:35.759
<v Speaker 3>probably in your contact adapter. That method gets the queer

132
00:06:35.839 --> 00:06:37.920
<v Speaker 3>parameters and the model name, so you have everything you

133
00:06:37.959 --> 00:06:41.279
<v Speaker 3>need to build that custom URL string like app contacts

134
00:06:41.360 --> 00:06:44.160
<v Speaker 3>by cityquery dot city and yeah, you might need to

135
00:06:44.160 --> 00:06:47.240
<v Speaker 3>remember to dasherize the city name turn los Angeles into

136
00:06:47.279 --> 00:06:49.879
<v Speaker 3>los Angeles, which is pretty standard for URLs.

137
00:06:49.959 --> 00:06:52.000
<v Speaker 2>Okay, that makes sense. You get full control over the

138
00:06:52.160 --> 00:06:55.800
<v Speaker 2>URL generation for different actions. And thinking about, say using

139
00:06:55.839 --> 00:06:58.839
<v Speaker 2>an external API like reddits. Their API for subreddit posts

140
00:06:58.920 --> 00:07:02.279
<v Speaker 2>is something like reddit dot com. Rememberjs dot Jason, we'd

141
00:07:02.360 --> 00:07:04.680
<v Speaker 2>use exactly that role for query override in a post

142
00:07:04.680 --> 00:07:07.279
<v Speaker 2>adapter to hit that specific nonstandard URL.

143
00:07:07.360 --> 00:07:07.519
<v Speaker 4>Right.

144
00:07:07.680 --> 00:07:11.639
<v Speaker 2>Absolutely. That's a perfect example of adapting to a completely external,

145
00:07:11.879 --> 00:07:16.160
<v Speaker 2>maybe slightly unusual API structure using the adapter hooks. And

146
00:07:16.199 --> 00:07:19.079
<v Speaker 2>while we're talking adapters, there's more fine grain control too.

147
00:07:19.439 --> 00:07:22.279
<v Speaker 2>You can influence how ember data decides whether to refetch

148
00:07:22.319 --> 00:07:25.079
<v Speaker 2>data that's already in the store, methods like should background

149
00:07:25.079 --> 00:07:28.079
<v Speaker 2>reload all or should background reload record. Let you return

150
00:07:28.160 --> 00:07:31.160
<v Speaker 2>true or false to control background updates.

151
00:07:31.279 --> 00:07:35.560
<v Speaker 3>So you can fine tune the caching behavior prevent unnecessary requests,

152
00:07:35.879 --> 00:07:37.000
<v Speaker 3>but still keep data fresh.

153
00:07:37.079 --> 00:07:39.959
<v Speaker 2>Precisely, maybe for certain data you always want the latest,

154
00:07:40.000 --> 00:07:42.959
<v Speaker 2>so you force a reload for other less critical data.

155
00:07:43.000 --> 00:07:45.000
<v Speaker 2>The cased version is fine for longer.

156
00:07:45.360 --> 00:07:48.879
<v Speaker 3>Very cool. Okay, let's switch gears to serializers. The translators.

157
00:07:49.360 --> 00:07:52.920
<v Speaker 3>APIs love different naming conventions, don't they snake case like

158
00:07:53.040 --> 00:07:57.480
<v Speaker 3>first name, title case CamelCase. Our JavaScript usually prefers CamelCase.

159
00:07:58.000 --> 00:08:00.560
<v Speaker 3>How do we bridge that gap without making our model ugly?

160
00:08:00.639 --> 00:08:04.199
<v Speaker 2>Oh yeah, the casing battle. Mber data has elegant solutions

161
00:08:04.199 --> 00:08:06.560
<v Speaker 2>for this. For just one or two specific fields, you

162
00:08:06.600 --> 00:08:09.519
<v Speaker 2>can use the actress hash in your serializer. You map

163
00:08:09.600 --> 00:08:12.319
<v Speaker 2>the model's camel case name to the API's key like

164
00:08:12.560 --> 00:08:13.040
<v Speaker 2>first name.

165
00:08:13.199 --> 00:08:15.759
<v Speaker 3>Oh, first name okay for isolated cases.

166
00:08:15.439 --> 00:08:19.000
<v Speaker 2>But if your entile API uses, say, snake case, doing

167
00:08:19.000 --> 00:08:21.839
<v Speaker 2>that for every attribute would be tedious. So instead you

168
00:08:21.879 --> 00:08:24.399
<v Speaker 2>override a method called key for attribute in your main

169
00:08:24.439 --> 00:08:28.639
<v Speaker 2>application serializer. This function receives the camel case attribute name

170
00:08:28.680 --> 00:08:31.879
<v Speaker 2>from your model, and you just return the transformed snakecase version.

171
00:08:32.440 --> 00:08:36.279
<v Speaker 2>Ember data then uses this for all attributes.

172
00:08:35.679 --> 00:08:38.559
<v Speaker 3>Automatically, nice like setting a global.

173
00:08:38.240 --> 00:08:41.799
<v Speaker 2>Rule exactly and again. Back to that Reddit example. Reddit

174
00:08:41.919 --> 00:08:45.000
<v Speaker 2>uses snake case for things like numb comments. Right, So

175
00:08:45.200 --> 00:08:48.120
<v Speaker 2>overwriting key for attribute lets our mber model use a

176
00:08:48.200 --> 00:08:51.720
<v Speaker 2>clean numb comments while the serializer handles translating it to

177
00:08:51.879 --> 00:08:54.360
<v Speaker 2>numb comments when talking to the Reddit API keeps the

178
00:08:54.360 --> 00:08:56.080
<v Speaker 2>front end cord nice and idiomatic.

179
00:08:56.399 --> 00:08:59.799
<v Speaker 3>Love it. What about relationships? APIs often just give you

180
00:08:59.840 --> 00:09:02.799
<v Speaker 3>a foreign key like companied. How do we link that

181
00:09:02.879 --> 00:09:05.360
<v Speaker 3>to a proper belongs to company relationship?

182
00:09:05.360 --> 00:09:09.000
<v Speaker 2>In Ember another common pattern, you can override key for

183
00:09:09.080 --> 00:09:13.519
<v Speaker 2>relationship in your serializer, similar to key for attribute. This

184
00:09:13.600 --> 00:09:17.120
<v Speaker 2>method lets you tell ember Data how relationship keys are

185
00:09:17.120 --> 00:09:20.120
<v Speaker 2>represented in the payload. You could tell it to expect

186
00:09:20.679 --> 00:09:24.159
<v Speaker 2>ad appended to the relationship name. For instance, so company

187
00:09:24.159 --> 00:09:25.399
<v Speaker 2>becomes companied, so.

188
00:09:25.399 --> 00:09:28.080
<v Speaker 3>It automates linking company to the company relationship. Yeap.

189
00:09:28.279 --> 00:09:31.000
<v Speaker 2>And one more quick one, what if your API doesn't

190
00:09:31.120 --> 00:09:34.120
<v Speaker 2>use e'd as the primary key, maybe uses eed or

191
00:09:34.200 --> 00:09:37.519
<v Speaker 2>SSN or something else. Just set the primary key property

192
00:09:37.559 --> 00:09:40.840
<v Speaker 2>on your serializer to whatever the API uses like primary

193
00:09:40.879 --> 00:09:43.840
<v Speaker 2>key ad. Mber Data will then know how to uniquely

194
00:09:43.879 --> 00:09:45.279
<v Speaker 2>identify your records.

195
00:09:45.679 --> 00:09:48.840
<v Speaker 3>Okay, handling keys casing relationships. That covers a lot of

196
00:09:48.879 --> 00:09:52.039
<v Speaker 3>common API quirks. Yeah, but what if the whole structure

197
00:09:52.039 --> 00:09:55.120
<v Speaker 3>of the response is just different, not just the keys,

198
00:09:55.120 --> 00:09:57.600
<v Speaker 3>but the nesting, the wrapping, Like that Reddit example where

199
00:09:57.639 --> 00:09:58.919
<v Speaker 3>the good stuff is buried deep.

200
00:09:59.519 --> 00:10:03.159
<v Speaker 2>Now we're talking normalization. This is the serializer's superpower for

201
00:10:03.320 --> 00:10:07.120
<v Speaker 2>reshaping incoming data. Let's say your API wraps everything in

202
00:10:07.159 --> 00:10:10.720
<v Speaker 2>a generic data key like data Yeah, you're chosen. Serializer

203
00:10:10.799 --> 00:10:15.159
<v Speaker 2>might not expect that wrapper, yes, so you override normalizer response.

204
00:10:15.919 --> 00:10:18.720
<v Speaker 2>This method gets the raw payload straight from the adapter.

205
00:10:19.320 --> 00:10:22.960
<v Speaker 2>Inside normalizer response, you can manipulate that payload. You could

206
00:10:23.000 --> 00:10:26.879
<v Speaker 2>say payload equal payload dot data to unwrap it. Then

207
00:10:27.159 --> 00:10:31.960
<v Speaker 2>crucially you call super dot normalizer response store primary model class, payload,

208
00:10:32.120 --> 00:10:36.480
<v Speaker 2>ID request type, passing the modified payload along. This lets

209
00:10:36.480 --> 00:10:40.240
<v Speaker 2>the standard normalization process take over with data it now understands.

210
00:10:40.360 --> 00:10:44.600
<v Speaker 3>Is there like preprocessing the raw response before Mberdata's main

211
00:10:44.639 --> 00:10:46.000
<v Speaker 3>normalization engine.

212
00:10:45.679 --> 00:10:48.200
<v Speaker 2>Sees it exactly, You're cleaning it up, reshaping it into

213
00:10:48.240 --> 00:10:52.240
<v Speaker 2>the format your base serializer, like Jason serializer Arrest serializer expects.

214
00:10:52.399 --> 00:10:55.120
<v Speaker 2>Remember ember Data's internal format it aims for is kind

215
00:10:55.120 --> 00:10:58.440
<v Speaker 2>of like jason dot API, but with singular, dasherized types

216
00:10:58.440 --> 00:11:02.559
<v Speaker 2>and camelcased attributes. Normalization bridges the gap between your API

217
00:11:02.639 --> 00:11:03.679
<v Speaker 2>and that internal format.

218
00:11:03.720 --> 00:11:05.960
<v Speaker 3>And for that Reddit example, with data nested under data

219
00:11:05.960 --> 00:11:09.279
<v Speaker 3>dot children, not data, that's where normalized response or maybe

220
00:11:09.279 --> 00:11:11.679
<v Speaker 3>a more specific one like normalized array response.

221
00:11:11.320 --> 00:11:16.000
<v Speaker 2>Comes in precisely, you'd override the appropriate normalized method, dig

222
00:11:16.000 --> 00:11:20.240
<v Speaker 2>into that nested structure, extract the array of actual post data,

223
00:11:20.639 --> 00:11:23.559
<v Speaker 2>maybe do some transformation on each item, and then pass

224
00:11:23.639 --> 00:11:26.159
<v Speaker 2>that cleaned up array to super makes sense.

225
00:11:26.320 --> 00:11:29.039
<v Speaker 3>It lets you handle really arbitrarily structured APIs.

226
00:11:29.159 --> 00:11:32.679
<v Speaker 2>It does, And normalized response actually delegates to more specific

227
00:11:32.759 --> 00:11:36.440
<v Speaker 2>methods based on the type of request normalized final response,

228
00:11:36.559 --> 00:11:39.600
<v Speaker 2>normalized find record response, normalized save response, etc. So you

229
00:11:39.600 --> 00:11:42.799
<v Speaker 2>can target your normalization logic very precisely if needed.

230
00:11:43.000 --> 00:11:46.879
<v Speaker 3>Super granular control. Now, when we send data back saving

231
00:11:47.000 --> 00:11:50.639
<v Speaker 3>or updating, you mentioned something called a snapshot object. Why

232
00:11:50.679 --> 00:11:51.360
<v Speaker 3>is that important?

233
00:11:51.480 --> 00:11:54.240
<v Speaker 2>Ah, yes, the snapshot. When you save a record, the

234
00:11:54.279 --> 00:11:57.080
<v Speaker 2>adapter doesn't get the live ember data record directly, it

235
00:11:57.080 --> 00:11:59.840
<v Speaker 2>gets a snapshot. Think of the snapshot as a re

236
00:12:00.159 --> 00:12:03.759
<v Speaker 2>only sort of frozen representation of the record's data at

237
00:12:03.759 --> 00:12:04.879
<v Speaker 2>that specific moment in time.

238
00:12:04.960 --> 00:12:06.919
<v Speaker 3>Okay, why not just use the live record.

239
00:12:06.679 --> 00:12:09.799
<v Speaker 2>Because accessing properties on a live Ember data record can

240
00:12:09.840 --> 00:12:14.120
<v Speaker 2>sometimes trigger side effects like automatically fetching unloaded relationships. You

241
00:12:14.159 --> 00:12:16.720
<v Speaker 2>don't want that happening accidentally when you're just trying to

242
00:12:16.759 --> 00:12:19.600
<v Speaker 2>package up data to send to the server. The snapshot

243
00:12:19.679 --> 00:12:22.200
<v Speaker 2>provides a safe, stable copy of the data for the

244
00:12:22.240 --> 00:12:25.919
<v Speaker 2>serializer to work with. Serialize into hash serialized methods. Use

245
00:12:25.960 --> 00:12:29.279
<v Speaker 2>it without any unexpected side effects. It guarantees you're only

246
00:12:29.320 --> 00:12:30.559
<v Speaker 2>sending the intended data.

247
00:12:30.679 --> 00:12:33.720
<v Speaker 3>Got it. It's like a safe copy for serialization purposes,

248
00:12:34.080 --> 00:12:35.679
<v Speaker 3>prevents unexpected data.

249
00:12:35.440 --> 00:12:38.039
<v Speaker 2>Loading exactly keeps things predictable.

250
00:12:38.279 --> 00:12:41.519
<v Speaker 3>Wow. Okay, that covers a ton of ground on adapting

251
00:12:41.559 --> 00:12:46.840
<v Speaker 3>the core communication. But what about more complex data patterns

252
00:12:47.559 --> 00:12:50.399
<v Speaker 3>like nested objects. What if my API sends back an

253
00:12:50.399 --> 00:12:53.200
<v Speaker 3>address object right inside the contact payload?

254
00:12:53.360 --> 00:12:55.840
<v Speaker 2>Good question. Mber data gives you a couple of options there.

255
00:12:56.039 --> 00:12:58.759
<v Speaker 2>For simple read only nested objects, where the address doesn't

256
00:12:58.799 --> 00:13:00.960
<v Speaker 2>really need to be its own manager, you can just

257
00:13:01.000 --> 00:13:04.480
<v Speaker 2>declare the attribute without a specific type or transform like

258
00:13:04.559 --> 00:13:07.399
<v Speaker 2>it at Bautry address. Mber data will just treat it

259
00:13:07.399 --> 00:13:10.879
<v Speaker 2>as a plain JavaScript object and pass it through Simple.

260
00:13:10.679 --> 00:13:13.000
<v Speaker 3>Okay for basic nested blobs of data.

261
00:13:13.039 --> 00:13:16.000
<v Speaker 2>But if that nested object like the address, has its

262
00:13:16.039 --> 00:13:19.440
<v Speaker 2>own ID and conceptually is a separate entity, you might

263
00:13:19.480 --> 00:13:22.679
<v Speaker 2>want to manage your link to elsewhere. Then you can

264
00:13:22.720 --> 00:13:25.639
<v Speaker 2>treat it as an embedded record. You use the embedded

265
00:13:25.639 --> 00:13:29.200
<v Speaker 2>records mixin in your serializer. This tells the serializer to

266
00:13:29.240 --> 00:13:32.240
<v Speaker 2>look for those nested objects and actually turn them into proper,

267
00:13:32.360 --> 00:13:36.159
<v Speaker 2>fully fledged MBER data records, establishing the has many or

268
00:13:36.200 --> 00:13:38.720
<v Speaker 2>belongs to relationship automatically, so.

269
00:13:38.679 --> 00:13:41.799
<v Speaker 3>It extracts the nested AID one three street mood yeah

270
00:13:41.840 --> 00:13:43.799
<v Speaker 3>and makes it a real address record linked.

271
00:13:43.639 --> 00:13:47.279
<v Speaker 2>To the contact precisely. Like if you have skills AID

272
00:13:47.600 --> 00:13:51.080
<v Speaker 2>one name, MBRA eighty two name texting embedded in a

273
00:13:51.200 --> 00:13:54.360
<v Speaker 2>user payload, the mixin can turn those into actual skill

274
00:13:54.399 --> 00:13:57.879
<v Speaker 2>records related to the user. One important caveat, though the

275
00:13:57.879 --> 00:14:01.320
<v Speaker 2>embedded records mixin is designed primarily for the rest serializer

276
00:14:01.399 --> 00:14:03.919
<v Speaker 2>or custom serializers, it doesn't really play nicely with the

277
00:14:03.919 --> 00:14:05.519
<v Speaker 2>strict Jason a PI serializer.

278
00:14:05.840 --> 00:14:08.840
<v Speaker 3>Okay, so if you're using strict Jason, that API embedding

279
00:14:08.879 --> 00:14:12.039
<v Speaker 3>isn't the standard approach anyway, Right, you'd use relationship.

280
00:14:11.440 --> 00:14:16.320
<v Speaker 2>Links exactly JSON that API prefers relationships defined by type

281
00:14:16.320 --> 00:14:20.559
<v Speaker 2>addresses ED one twenty three in a relationships block rather

282
00:14:20.600 --> 00:14:23.879
<v Speaker 2>than embedding the full address object directly under the contact.

283
00:14:24.039 --> 00:14:26.000
<v Speaker 3>That makes sense. Use the tool that fits the standard

284
00:14:26.000 --> 00:14:26.480
<v Speaker 3>you're working with.

285
00:14:26.639 --> 00:14:29.679
<v Speaker 2>Right, Embedded records are powerful for certain API styles, but

286
00:14:29.720 --> 00:14:31.879
<v Speaker 2>maybe not the JSON dot API way.

287
00:14:32.000 --> 00:14:36.000
<v Speaker 3>Okay, moving on errors they happen. How does mber data

288
00:14:36.080 --> 00:14:38.120
<v Speaker 3>help us handle API errors gracefully?

289
00:14:38.399 --> 00:14:41.240
<v Speaker 2>It actually has pretty robust built in error handling. It

290
00:14:41.279 --> 00:14:45.120
<v Speaker 2>maps common HTTP status codes to specific error objects. The

291
00:14:45.120 --> 00:14:47.679
<v Speaker 2>most common one is probably four hundred and twenty two

292
00:14:47.840 --> 00:14:51.720
<v Speaker 2>unprocessable entity. Mber data treats this as a validation error

293
00:14:51.720 --> 00:14:55.279
<v Speaker 2>and creates an invalid air object. Importantly, this invalid air

294
00:14:55.320 --> 00:14:58.039
<v Speaker 2>expects the API response to follow the JSON dot API

295
00:14:58.159 --> 00:15:01.120
<v Speaker 2>error object specification with d DE tales about what went wrong,

296
00:15:01.240 --> 00:15:03.720
<v Speaker 2>often including pointers to the specific fields.

297
00:15:03.360 --> 00:15:08.840
<v Speaker 3>So it expects errors detail marted source pointer data attributes.

298
00:15:08.320 --> 00:15:12.200
<v Speaker 2>Femail ideally yes. That allows you to easily display validation

299
00:15:12.279 --> 00:15:15.399
<v Speaker 2>messages next to the correct form fields. For example, It

300
00:15:15.399 --> 00:15:18.919
<v Speaker 2>also maps other codes four one becomes an unauthorized error,

301
00:15:19.159 --> 00:15:21.440
<v Speaker 2>four or three of forbidden AER for a four and

302
00:15:21.519 --> 00:15:24.200
<v Speaker 2>not founder four on nine a conflict error, and five

303
00:15:24.279 --> 00:15:27.360
<v Speaker 2>hundred range usually a server er. These all inherit from

304
00:15:27.399 --> 00:15:28.840
<v Speaker 2>a base adapter AIR class.

305
00:15:28.879 --> 00:15:32.159
<v Speaker 3>That's handy, but what if my API uses say, four

306
00:15:32.240 --> 00:15:34.600
<v Speaker 3>hundred bad requests for validation airs instead of four to

307
00:15:34.600 --> 00:15:35.000
<v Speaker 3>twenty two.

308
00:15:35.159 --> 00:15:38.200
<v Speaker 2>You can customize that the adapter has an is invalid

309
00:15:38.480 --> 00:15:43.080
<v Speaker 2>status Header's payload method, you can override it to return true.

310
00:15:43.120 --> 00:15:45.240
<v Speaker 2>If the status code is four hundred or whatever your

311
00:15:45.240 --> 00:15:48.120
<v Speaker 2>API uses telling ember data to treat it as an

312
00:15:48.120 --> 00:15:48.840
<v Speaker 2>invalid error.

313
00:15:49.080 --> 00:15:51.399
<v Speaker 3>Okay, so we can map status codes. What about the

314
00:15:51.519 --> 00:15:54.679
<v Speaker 3>error payload itself? What if it's not Jason dot API compliant.

315
00:15:54.960 --> 00:15:57.559
<v Speaker 2>Two main places to hook in there. For general error

316
00:15:57.559 --> 00:16:00.879
<v Speaker 2>response shaping, you can override handle response in adapter that

317
00:16:00.919 --> 00:16:03.679
<v Speaker 2>gives you the raw response regardless of status. But if

318
00:16:03.720 --> 00:16:07.200
<v Speaker 2>you specifically want to normalize the structure of validation error messages,

319
00:16:07.279 --> 00:16:10.399
<v Speaker 2>like transforming your API's custom air format into the json

320
00:16:10.440 --> 00:16:13.200
<v Speaker 2>dot api ers array, the extra errors method on the

321
00:16:13.240 --> 00:16:16.919
<v Speaker 2>serializer is usually the better place. It's semantically focused on error.

322
00:16:16.840 --> 00:16:20.759
<v Speaker 3>Payload interpretation adapter for status code mapping and general handling

323
00:16:21.200 --> 00:16:23.519
<v Speaker 3>serializer for normalizing the air content.

324
00:16:24.120 --> 00:16:24.759
<v Speaker 2>Got you got it.

325
00:16:24.879 --> 00:16:28.879
<v Speaker 3>Let's tackle something a bit more mind vending. Polymorphic relationships,

326
00:16:29.519 --> 00:16:32.279
<v Speaker 3>where a relationship can point to different types of records,

327
00:16:32.399 --> 00:16:34.919
<v Speaker 3>like a notification could be about a new comment or

328
00:16:34.960 --> 00:16:36.039
<v Speaker 3>a friend request. Ah.

329
00:16:36.159 --> 00:16:40.759
<v Speaker 2>Yes, polymorphism very powerful for certain data models. You enable

330
00:16:40.799 --> 00:16:43.360
<v Speaker 2>this in your model by setting polymorphic true on the

331
00:16:43.440 --> 00:16:47.519
<v Speaker 2>belongs to or has many relationship definition. The key requirement

332
00:16:47.600 --> 00:16:50.960
<v Speaker 2>then falls on the API response When including that relationship

333
00:16:51.039 --> 00:16:54.759
<v Speaker 2>data either sideloaded or linked. The API must provide both

334
00:16:54.799 --> 00:16:57.360
<v Speaker 2>the ID and the type for each related record.

335
00:16:57.519 --> 00:17:00.519
<v Speaker 3>So like add five foot type new comment or ABC

336
00:17:01.120 --> 00:17:02.919
<v Speaker 3>type friend request.

337
00:17:02.639 --> 00:17:06.480
<v Speaker 2>Exactly that type tells Ember data which specific model new

338
00:17:06.480 --> 00:17:09.400
<v Speaker 2>comment or friend request to load for that relationship link.

339
00:17:09.680 --> 00:17:12.000
<v Speaker 2>Of course, those models should ideally inherit from a common

340
00:17:12.039 --> 00:17:14.319
<v Speaker 2>base model like notification subject and can.

341
00:17:14.240 --> 00:17:17.759
<v Speaker 3>You customize how that type information is read or written

342
00:17:18.079 --> 00:17:20.000
<v Speaker 3>if the EPI uses a non standard way.

343
00:17:20.160 --> 00:17:24.279
<v Speaker 2>Absolutely. The serializer offers hooks like key for polymorphic type,

344
00:17:24.759 --> 00:17:29.680
<v Speaker 2>serialize polymorphic type, and extract polymorphic relationship to handle custom

345
00:17:29.759 --> 00:17:34.319
<v Speaker 2>conventions for identifying and processing those polymorphic types in the payload.

346
00:17:34.359 --> 00:17:37.119
<v Speaker 3>Incredible flexibility there. It really feels like you can mold

347
00:17:37.240 --> 00:17:40.319
<v Speaker 3>MBER data to almost anything, which brings us to testing.

348
00:17:40.559 --> 00:17:44.039
<v Speaker 3>With all these potential customizations and adapters and serializers, how

349
00:17:44.039 --> 00:17:46.839
<v Speaker 3>do we make sure they actually work correctly and don't

350
00:17:46.839 --> 00:17:47.400
<v Speaker 3>break later?

351
00:17:47.640 --> 00:17:50.759
<v Speaker 2>Testing is absolutely critical. Yes, you wouldn't build a complex

352
00:17:50.799 --> 00:17:53.960
<v Speaker 2>machine without testing the parts right. You can unit test

353
00:17:53.960 --> 00:17:57.519
<v Speaker 2>adapters and serializers in isolation. For an adapter, you might

354
00:17:57.559 --> 00:18:00.839
<v Speaker 2>call EARL four query directly and assert the output URL.

355
00:18:01.240 --> 00:18:04.000
<v Speaker 2>For a serializer, you could test key for attribute or

356
00:18:04.079 --> 00:18:05.599
<v Speaker 2>normalize with sample payloads.

357
00:18:05.680 --> 00:18:08.119
<v Speaker 3>Okay, unit tests for specific methods.

358
00:18:07.839 --> 00:18:10.759
<v Speaker 2>But often the most valuable tests are integration tests that

359
00:18:10.839 --> 00:18:14.079
<v Speaker 2>exercise the adapter and serializer together working through the store.

360
00:18:14.440 --> 00:18:17.880
<v Speaker 2>This more closely mirrors how your application actually uses them.

361
00:18:18.200 --> 00:18:20.599
<v Speaker 2>You'd use the store to find or save a record,

362
00:18:20.799 --> 00:18:23.240
<v Speaker 2>and then you can assert things about the outgoing request,

363
00:18:23.680 --> 00:18:26.759
<v Speaker 2>like the URL or payload sent by the adapter, serial

364
00:18:26.839 --> 00:18:29.160
<v Speaker 2>ether combo, or the data that ends up in the

365
00:18:29.240 --> 00:18:30.640
<v Speaker 2>store after normalization.

366
00:18:31.039 --> 00:18:33.319
<v Speaker 3>And how do you do that without hitting a real API.

367
00:18:33.759 --> 00:18:37.279
<v Speaker 2>Tools like Embercli Mirage are perfect for this. Mirage lets

368
00:18:37.319 --> 00:18:41.079
<v Speaker 2>you easily define mock API endpoints right within your Mber app.

369
00:18:41.400 --> 00:18:44.319
<v Speaker 2>So your test run against this predictable mock server. You

370
00:18:44.319 --> 00:18:47.440
<v Speaker 2>can make the store fetch data, Mirage intercepts it returns

371
00:18:47.440 --> 00:18:50.000
<v Speaker 2>a specific payload you defined, and then you can assert

372
00:18:50.000 --> 00:18:53.640
<v Speaker 2>that your serializer normalized it correctly into the store, or

373
00:18:53.799 --> 00:18:56.960
<v Speaker 2>assert that saving a record sent the correctly serialized payload

374
00:18:57.000 --> 00:18:57.720
<v Speaker 2>to Mirage.

375
00:18:58.240 --> 00:19:01.200
<v Speaker 3>So Mirage acts as the customized fake back end for

376
00:19:01.279 --> 00:19:04.200
<v Speaker 3>testing the whole store adapter serializer stack precisely.

377
00:19:04.440 --> 00:19:06.960
<v Speaker 2>It gives you high confidence that your data layer customizations

378
00:19:06.960 --> 00:19:08.079
<v Speaker 2>are working as intended.

379
00:19:08.319 --> 00:19:10.200
<v Speaker 3>Right, That makes a lot of sense. Test the whole flow.

380
00:19:10.480 --> 00:19:12.759
<v Speaker 3>So let's tie this all together. What's the big takeaway

381
00:19:12.759 --> 00:19:17.160
<v Speaker 3>for everyone listening. We've gone through the core part store, adapter, serializer.

382
00:19:17.720 --> 00:19:21.559
<v Speaker 3>We've seen how to tweak URLs, map keys, handle nesting,

383
00:19:21.640 --> 00:19:24.440
<v Speaker 3>manage errors, even deal with polymorphism.

384
00:19:24.759 --> 00:19:27.000
<v Speaker 2>I think the main point is that ember data isn't

385
00:19:27.039 --> 00:19:30.519
<v Speaker 2>just about fetching data in one specific, prescribed way. It's

386
00:19:30.599 --> 00:19:34.000
<v Speaker 2>really about giving you, the developer, the power to create

387
00:19:34.200 --> 00:19:38.079
<v Speaker 2>clean abstractions over any kind of API, no matter how

388
00:19:38.119 --> 00:19:41.599
<v Speaker 2>complex or non standard it might be. It provides strong

389
00:19:41.640 --> 00:19:44.240
<v Speaker 2>conventions as a starting point, which is great for productivity,

390
00:19:44.839 --> 00:19:48.119
<v Speaker 2>but it's real strength, it's genius lies in these thoughtful

391
00:19:48.119 --> 00:19:51.440
<v Speaker 2>extension points, the adapter and serializer hooks that let you

392
00:19:51.480 --> 00:19:55.160
<v Speaker 2>handle the inevitable real world variations. It frees you up

393
00:19:55.160 --> 00:19:57.880
<v Speaker 2>to focus on building the actual features and user experience,

394
00:19:57.960 --> 00:20:00.319
<v Speaker 2>rather than getting bogged down in the messy detail of

395
00:20:00.400 --> 00:20:03.200
<v Speaker 2>data fetching and translation for every single API call.

396
00:20:03.519 --> 00:20:06.519
<v Speaker 3>So, whether your API is a perfect JSON dot API

397
00:20:06.599 --> 00:20:10.920
<v Speaker 3>implementation or something a bit more creative. From the back

398
00:20:11.000 --> 00:20:11.640
<v Speaker 3>end team.

399
00:20:11.559 --> 00:20:14.240
<v Speaker 4>Mber Data's extensibility means you likely have the tools to

400
00:20:14.240 --> 00:20:17.119
<v Speaker 4>make it work cleanly within your MBER application. Hopefully this

401
00:20:17.160 --> 00:20:18.960
<v Speaker 4>deep dive has shown you not just how to use

402
00:20:18.960 --> 00:20:20.960
<v Speaker 4>these tools, but why they're designed the way they are,

403
00:20:21.400 --> 00:20:24.440
<v Speaker 4>empowering you to really master your application's data flow. Think

404
00:20:24.480 --> 00:20:27.200
<v Speaker 4>about your own projects. Which of these techniques Overwriting EARL

405
00:20:27.240 --> 00:20:31.400
<v Speaker 4>for query, customizing key for attribute, using normalized response might

406
00:20:31.480 --> 00:20:34.799
<v Speaker 4>solve that nagging API integration headache you've been avoiding. The

407
00:20:34.880 --> 00:20:37.599
<v Speaker 4>tools are there. That's our time for this deep dive.

408
00:20:37.759 --> 00:20:41.160
<v Speaker 4>Until next time, keep exploring, keep customizing, and keep learning.
