Deprecate Implicit Record Loading in Routes
Summary
This RFC seeks to deprecate and remove the default record loading behaviour on Ember's Route. By consequence, this will also deprecate and remove the default store on every Route. This behaviour is likely something you either know you have or do not know but it may be occuring in your app.
export default class PostRoute extends Route {
beforeModel() {
// do stuff
}
afterModel() {
// do stuff
}
}
In this example, the model
hook is not defined. However, Ember will attempt to try a few things before rendering this route's template.
If there is a
store
property on your route, it will attempt to call it'sfind
method. Assuming you haveember-data
installed, you may be expecting this. The arguments will be extracted from the params. a. For example, if a dynamic segment is:post_id
, there exists logic to split on the underscore and find a record of typepost
.As a fallback, it will attempt to define a
find
method and use yourModel
instance's find method to fetch. If aModel
cannot be found or if the foundModel
does not have afind
method, an assertion is thrown.
Motivation
If a user does not define a model
hook, a side effect of going to the network has long confused developers. Users have come to associate Route.model()
with a hook that returns ember-data
models in the absense of explicit injection. While this can be true, it is not wholly true. New patterns of data loading are becoming accepted in the community including opting to fetch data in a Component or using different libraries.
By removing this behaviour, we will encourage developers to explicitly define what data is being fetched and from where.
Detailed design
We will issue a deprecation to findModel
notifying the user that if they want to continue this behaviour of attempting to fetch a resource implicitly, they should try and replicate with their own explicitly defined model
hook.
In addition, we will include an optional feature to disable this feature and clear the deprecation. This optional feature will be enabled in the blueprint because we want new apps to get this behaviour by default.
In v6.0.0, we will remove findModel
and logic to determine arguments for this method. This will not remove returning the transition
context when no model
hook is defined. The optional feature will also be removed.
How we teach this
Most of this behaviour is lightly documented. Developers often come to this by mistake after some difficult searching. First, we will have to remove this sentence from the docs.
The first reason is that Routes know how to fetch the right model by default, if you follow the convention.
A direct one to one replacement might look like this.
import { inject as service } from '@ember/service';
export default class PostRoute extends Route {
// assuming you have ember-data installed
@service store;
beforeModel() {
// do stuff
}
model({ post_id }) {
return this.store.findRecord('post', post_id);
}
afterModel() {
// do stuff
}
}
Alternatives
- Continue to provide fallback fetching behaviour but ensure no
assert
is called for users that have neither a store nor aModel
with afind
method.