Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support @attr decorator without parens #6328

Closed
chancancode opened this issue Aug 15, 2019 · 3 comments
Closed

Support @attr decorator without parens #6328

chancancode opened this issue Aug 15, 2019 · 3 comments
Assignees

Comments

@chancancode
Copy link
Member

Before...

import Model, { attr } from '@ember-data/model';

export default class RentalModel extends Model {
  @attr() title;
  @attr() owner;
  @attr() city;
  @attr() location;
  @attr() category;
  @attr() image;
  @attr() bedrooms;
  @attr() description;
}

After...

import Model, { attr } from '@ember-data/model';

export default class RentalModel extends Model {
  @attr title;
  @attr owner;
  @attr city;
  @attr location;
  @attr category;
  @attr image;
  @attr bedrooms;
  @attr description;
}

The parens version is still supported and required when you need to specify a transform type.

This matches how the built-in Ember decorators work, which makes it easier to explain @attr in the guides, building on what they already learned from the Ember side, without having to explain the gratuitous difference.

chancancode added a commit to ember-learn/super-rentals that referenced this issue Aug 15, 2019
* Now that we have added a few features, it's time to do some cleaning up again
* When we added the `rental` route, we more or less duplicated the code form the `index` route
* This is obviously not ideal
  * For the usual reasons that duplications are undesirable (changing multiple files for the same conceptual change, etc)
  * But also, all our our server's API endpoints follow the JSON:API format, so potentailly we will have to copy this for all routes
* Fortunately, there is a better way, welcome to Ember Data

* Ember Data is a <...some one-line official description?...>
* It offers a lot of useful features for managing state and data in a client-side application

* But for starter, the most relevant feature to our immediate problem:
  * It offers an _adapter_ API
  * As long as your server uses a consistnent format across all the endpoints, you can write an adapter to deal with the mapping once-and-for-all
    * Don't worry, if your server is a bit inconsistent at times, you can have per-model adapters too

* JSON:API happens to be Ember Data's default adapter
  * Since our server follows the same convention, this is great news for us
* But our server differs slightly from Ember Data's assumptions in two minor ways
  * Ember Data expects to find the endpoints at `/rentals`, `/rentals/:rental_id`, etc
  * Our server servers them at `/api/rentals.json`, `/api/rentals/:rental_id.json`, etc
* In other words
  * We have an `/api` _namespace_ prefix on all resource URLs, and
  * We have a `.json` extension at the end

* Even though Ember Data has some default assumptions, it is also easy to customize:

<!-- TODO: show diff for app/adapters/application.js -->

* Here, we created an _application adapter_
* This is the adapter that is used, by default, for all resources (models) in the aoo
* We subclass from the default `JSONAPIAdapter`
* Having a `namespace` is pretty popular, so Ember Data has an API for that
* The extension is less common and doesn't have a declaritve configuration API, but we can just override the `buildURL` method to add it

* The next step is to create a `rental` model class

<!-- TODO: show diff for model -->

* A model class holds the data for a resource
* In this case, an instance of the `RentalModel` holds the information for an individual rental property
* We declared the attributes that are part of this model using the `@attr` decorator
  * They can be accessed as `someRental.title`, `someRental.location.lat`, etc

<!-- TODO: track emberjs/data#6328 and remove the () -->

* Since we now have a class, we can now add a `type` getter
  * It can be accessed as `someRental.type`, just like a "real" attribute
  * Futher, `@attr` implies `@tracked`, so when `category` is updated, `type` would too

* We can add a _model test_ for this

<!-- TODO: show diff for test -->

* This kind of test is also known as a _unit test_
  * Because, unlike the other kind of tests we have written before, this doesn't render anything
  * It simply instantiate the model object and manipulate/test it directly

* With the adapter and model setup, we can vastly cleanup our routes:

<!-- TODO: show diff -->

* Wow! We removed a lot of duplicated code, and all our tests still pass!

* Ember Data provides a _store_, from which we can find our models
  * We can gain access to it by injecting the store service
  * The store acts as an intermediary between our app and our server
  * Among other things, it caches the responses
  * If we already requested the same data and have it locally, it can return them immediately without waitig for the server
  * Otherwise, it go fetch it from our server, taking into account our adapter configuration, and caches the response for next time

* Ember Data has a lot more features to offer, like managing relationships between models
* But that's all about Ember Data for now/in this tutorial
@runspired
Copy link
Contributor

Did we determine whether this was even possible? It wasn't last I looked into it due to our required support matrix.

chancancode added a commit to ember-learn/super-rentals that referenced this issue Aug 15, 2019
* Now that we have added a few features, it's time to do some cleaning up again
* When we added the `rental` route, we more or less duplicated the code form the `index` route
* This is obviously not ideal
  * For the usual reasons that duplications are undesirable (changing multiple files for the same conceptual change, etc)
  * But also, all our our server's API endpoints follow the JSON:API format, so potentailly we will have to copy this for all routes
* Fortunately, there is a better way, welcome to Ember Data

* Ember Data is a <...some one-line official description?...>
* It offers a lot of useful features for managing state and data in a client-side application

* But for starter, the most relevant feature to our immediate problem:
  * It offers an _adapter_ API
  * As long as your server uses a consistnent format across all the endpoints, you can write an adapter to deal with the mapping once-and-for-all
    * Don't worry, if your server is a bit inconsistent at times, you can have per-model adapters too

* JSON:API happens to be Ember Data's default adapter
  * Since our server follows the same convention, this is great news for us
* But our server differs slightly from Ember Data's assumptions in two minor ways
  * Ember Data expects to find the endpoints at `/rentals`, `/rentals/:rental_id`, etc
  * Our server servers them at `/api/rentals.json`, `/api/rentals/:rental_id.json`, etc
* In other words
  * We have an `/api` _namespace_ prefix on all resource URLs, and
  * We have a `.json` extension at the end

* Even though Ember Data has some default assumptions, it is also easy to customize:

<!-- TODO: show diff for app/adapters/application.js -->

* Here, we created an _application adapter_
* This is the adapter that is used, by default, for all resources (models) in the aoo
* We subclass from the default `JSONAPIAdapter`
* Having a `namespace` is pretty popular, so Ember Data has an API for that
* The extension is less common and doesn't have a declaritve configuration API, but we can just override the `buildURL` method to add it

* The next step is to create a `rental` model class

<!-- TODO: show diff for model -->

* A model class holds the data for a resource
* In this case, an instance of the `RentalModel` holds the information for an individual rental property
* We declared the attributes that are part of this model using the `@attr` decorator
  * They can be accessed as `someRental.title`, `someRental.location.lat`, etc

<!-- TODO: track emberjs/data#6328 and remove the () -->

* Since we now have a class, we can now add a `type` getter
  * It can be accessed as `someRental.type`, just like a "real" attribute
  * Futher, `@attr` implies `@tracked`, so when `category` is updated, `type` would too

* We can add a _model test_ for this

<!-- TODO: show diff for test -->

* This kind of test is also known as a _unit test_
  * Because, unlike the other kind of tests we have written before, this doesn't render anything
  * It simply instantiate the model object and manipulate/test it directly

* With the adapter and model setup, we can vastly cleanup our routes:

<!-- TODO: show diff -->

* Wow! We removed a lot of duplicated code, and all our tests still pass!

* Ember Data provides a _store_, from which we can find our models
  * We can gain access to it by injecting the store service
  * The store acts as an intermediary between our app and our server
  * Among other things, it caches the responses
  * If we already requested the same data and have it locally, it can return them immediately without waitig for the server
  * Otherwise, it go fetch it from our server, taking into account our adapter configuration, and caches the response for next time

* Ember Data has a lot more features to offer, like managing relationships between models
* But that's all about Ember Data for now/in this tutorial
@pzuraq
Copy link

pzuraq commented Aug 15, 2019

It should be possible, using compatibility helpers if necessary.

@runspired
Copy link
Contributor

resolved by #6339 for the most recent ember versions (not 3.8 LTS and likely not some versions thereafter) cc @pzuraq

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants