Skip to content

Commit

Permalink
add deprecation guides
Browse files Browse the repository at this point in the history
  • Loading branch information
Chris Garrett committed Dec 6, 2020
1 parent 435e17c commit 2c8d204
Showing 1 changed file with 160 additions and 0 deletions.
160 changes: 160 additions & 0 deletions text/0680-implicit-injection-deprecation.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,166 @@ The API docs would need to be overhauld in a few spots. First, we need to remove

The default blueprints when generating a new Ember application will not change.

### Deprecation Guides

#### Stage 1

Implicit injections are injections that are made by telling Ember to inject a
service (or another type of value) into every instance of a specific type of
object. A common example of this was the `store` property that was injected into
routes and controllers when users installed Ember Data by default.

```js
export default class ApplicationRoute extends Route {
model() {
return this.store.findQuery('user', 123);
}
}
```

Notice how the user can access `this.store` without having declared the store
service using the `@service` decorator. This was accomplished by using the
`owner.inject` API, usually in an initializer:

```js
export default {
initialize(app) {
app.inject('route', 'store', 'service:store');
app.inject('controller', 'store', 'service:store');
}
}
```

Implicit injections are difficult to understand, both because it's not obvious
that they exist, or where they come from.

In general, in order to migrate away from this pattern, you should use an
explicit injection instead of an implicit one. You can do this by using the
`@service` decorator wherever you are using the implicit injection currently.

Before:

```js
import { Route } from '@ember/routing/route';

export default class ApplicationRoute extends Route {
model() {
return this.store.findQuery('user', 123);
}
}
```

After:

```js
import { Route } from '@ember/routing/route';
import { inject as service } from '@ember/service';

export default class ApplicationRoute extends Route {
@service store;

model() {
return this.store.findQuery('user', 123);
}
}
```

In some cases, you may be using an injected value which is not a service.
Injections of non-service values do not have a direct explicit-injection
equivalent. As such, to migrate away from these, you will have to rewrite the
injection to use services instead.

Before:

```js
// app/initializers/logger.js
import EmberObject from '@ember/object';

export function initialize(application) {
let Logger = EmberObject.extend({
log(m) {
console.log(m);
}
});

application.register('logger:main', Logger);
application.inject('route', 'logger', 'logger:main');
}

export default {
name: 'logger',
initialize: initialize
};
```
```js
// app/routes/application.js
export default class ApplicationRoute extends Route {
model() {
this.logger.log('fetching application model...');
//...
}
}
```

After:

```js
// app/services/logger.js
import Service from '@ember/service';

export class Logger extends Service {
log(m) {
console.log(m);
}
}
```
```js
// app/routes/application.js
import { inject as service } from '@ember/service';

export default class ApplicationRoute extends Route {
@service logger;

model() {
this.logger.log('fetching application model...');
//...
}
}
```

### Stage 2

The `owner.inject` API would previously inject a values into every instance of a
particular type of class. For instance, you could inject the `store` service
automatically into every controller and route:


```js
export default {
initialize(app) {
app.inject('route', 'store', 'service:store');
app.inject('controller', 'store', 'service:store');
}
}
```

And in doing so, users could use the value without explicitly declaring it in
that type of object, using `@service`:

```js
import { Route } from '@ember/routing/route';

export default class ApplicationRoute extends Route {
model() {
return this.store.findQuery('user', 123);
}
}
```

This ability was deprecated and removed in Ember v4.0.0, so users no longer can
do this, even if you are using the `owner.inject` API. It instead does nothing,
so you can safely remove it without any other changes necessary.

## Alternatives

- Continue with use of `owner.inject` but overhaul docs and recommend explicit injection.
Expand Down

0 comments on commit 2c8d204

Please sign in to comment.