Debugging Ember
(without tears)
@vaidehijoshi


💕
💕
community
documentation
easy to use
...most of the time
Debugging
🐞
🐝

It's hard.
And frustrating.
Maybe I should give up?
get stuck
un
let's debug together!
Bug #1
🐛



😮
wait...what!?


narrow down the of the problem
scope
the view
<h3>Recipes</h3>
<table>
<thead>
<tr>
<th>Name</th>
<th>Date</th>
</tr>
</thead>
<tbody>
{{#each sortedRecipes key='id' as |recipe|}}
<tr>
<td>
{{#link-to 'recipe' recipe}}{{recipe.name}}{{/link-to}}
</td>
<td>
{{time-format recipe.published_at 'l'}}
</td>
</tr>
{{/each}}
</tbody>
</table>
<hr>
<button {{action "newRecipe"}}>New Recipe</button>
👍
{{#link-to 'recipe' recipe}}
{{recipe.name}}
{{/link-to}}
👍
the route
it's not the view.
maybe it's
// router.js
import Ember from 'ember';
Router.map(function() {
this.route('recipe', {
path: '/recipe/:id'
});
});
dynamic segment
// recipe.js
import Ember from 'ember';
export default Ember.Route.extend({
});
the model
what does our route have access to?
where
does it get access to it?
// recipe.js
import Ember from 'ember';
export default Ember.Route.extend({
});
// model hook!
model(params) {
return this.store.find('recipe', params.id);
}
return a promise
Ember Data record
javaScript object
javaScript array
model(params) {
debugger;
return this.store.find('recipe', params.id);
}
yah yah yah, but will it work?
(also: how does it work?)



and when we refresh:
🎊


in our ember inspector:
import Ember from 'ember';
export default Ember.Route.extend({
// model(params) {
// return this.store.find('recipe', params.id);
// }
});
so.
what's different?
where did we start?
the view
1/
link-to
2/
the route directly
documentation is our friend.


our route never knew how to get its model!
🙊
model hooks don't
fire when using
link-to helpers
🐛
Bug #2
🐜

Ember Meetup
Party Supplies

Party Supplies
1. Avocados
2. Pepper Jack Cheese
😱
why are our model properties wrong?
where do model properties come from?
the route
import Ember from 'ember';
export default Ember.Route.extend({
model() {
return this.store.find('grocery-list', params.id);
}
});
import Ember from 'ember';
export default Ember.Controller.extend({
name: null,
items: null
});

Party Supplies
1. Avocados
2. Pepper Jack Cheese
our controller had values set at least once.
maybe we need to set them again?
does a controller get its properties from?
where
...are we setting them correctly?


// grocery-list.js
import Ember from 'ember';
export default Ember.Route.extend({
model(params) {
return this.store.find('grocery-list', params.id);
},
setupController(controller, model) {
this._super(controller, model);
}
});
setupController(controller, model) {
this._super(controller, model);
controller.setProperties(
model.getProperties([
'name',
'items'
])
);
}
find model
pull values from it
set them on our controller

Ember Meetup
Party Supplies

Ember Meetup
Tomster food!
we never told our controller to set its properties!
🙊
controllers are singletons
persisted state
🐜
controllers are singletons
routeable components!
controllers are singletons
Bug #3
🐌

😭
what do we have
to?
access
what's being passed in?
{{recipe-editor recipe=model afterDestroy='afterDestroy'}}
where do they come from?
import Ember from 'ember';
export default Ember.Route.extend({
model(params) {
return this.store.find('recipe', params.id);
},
actions: {
afterDestroy() {
this.transitionTo('recipes');
}
}
});
<button {{action 'deleteRecipe'}}>
Delete
</button>
how is it being passed?
import Ember from 'ember';
export default Ember.Component.extend({
recipe: null,
saveRecipe() {
// logic to save recipe
},
deleteRecipe() {
const recipe = this.get('recipe');
if (confirm('Are you sure?')) {
recipe.destroyRecord().then(() => {
afterDestroy();
});
}
}
});



{{recipe-editor recipe=model afterDestroy='afterDestroy'}}
deleteRecipe() {
const recipe = this.get('recipe');
if (confirm('Are you sure?')) {
recipe.destroyRecord().then(() => {
afterDestroy();
});
}
}
this.afterDestroy();
this.sendAction('afterDestroy');
afterDestroy();
👎
🚫
❓
deleteRecipe() {
const recipe = this.get('recipe');
if (confirm('Are you sure?')) {
recipe.destroyRecord().then(() => {
this.sendAction('afterDestroy');
});
}
}


🎉



// recipe-editor/template.js
<recipe-editor recipe=model destroy={{action 'afterDestroy'}}>
// recipe-editor/component.js
export default Ember.Component.extend({
actions: {
deleteRecipe() {
const recipe = this.get('recipe');
recipe.destroyRecord().then(() => {
this.attrs.destroy();
}
}
}
});
angle-bracket way!
actions are fired on our current context
🐌

developing with ember:
superpowers!
Computers
¯\_(ツ)_/¯

understand what's happening in our code?
not cry while debugging?
understand what's happening in our code?
🐞
getting stuck.
getting unstuck.
asking questions!
all the
check our assumptions
narrow down the scope of the problem
figure out what we have access to
lean on resources + docs
1/
2/
3/
4/
code's
point of view

frustrated
💖
fun
frustrated
Thanks!
@vaidehijoshi
🐞
Debugging Ember
By Vaidehi Joshi
Debugging Ember
- 1,324