` and it also erroneously will create an extra history state if a user clicks on something that transitions to that route again, since it will change `location.hash === '#/foo'`.
-
-This ability will be removed quickly to allow us to mimick the browser's behavior of scrolling the page to an element who's id matches, but in our case doing so after the transition ends and everything is rendered. Once this feature is added, you'll be able to link to id's even with doubled up hashes: `#/foo#some-id` as well as the expected `#some-id`.
-
-### Deprecations Added in 1.9
-
-#### More Consistent Handlebars Scope
-
-In today's Ember, the `each` and `with` helpers come in two flavors: a "context-switching" flavor and a "named-parameter" flavor.
-
-```handlebars
-{{#each post in posts}}
- {{!-- the context in here is the same as the outside context,
- and `post` references the current iteration --}}
-{{/each}}
-
-{{#each posts}}
- {{!-- the context in here has shifted to the individual post.
- the outer context is no longer accessible --}}
-{{/each}}
-
-{{#with post as otherPost}}
- {{!-- the context in here is the same as the outside context }}
-{{/with}}
-
-{{#with post}}
- {{!-- the context in here has shifted to the post.
- the outer context is no longer accessible --}}
-{{/with}}
-```
-
-This has proven to be one of the more confusing parts of the Ember templating system. It is also not clear to
-beginners which to use, and when they choose the context-shifting form, they lose access to values in the outer
-context that may be important.
-
-Because the helper itself offers no clue about the context-shifting behavior, it is easy (even for more experienced
-Ember developers) to get confused when skimming a template about which object a value refers to.
-
-The context-shifting forms of `#each` and `#with` have been deprecated in favor of the named-parameter forms.
-
-##### Transition Plan
-
-To transition your code to the new syntax, you can change templates that look like this:
-
-```handlebars
-{{#each people}}
-
{{firstName}} {{lastName}}
-
{{address}}
-{{/each}}
-```
-
-with:
-
-```handlebars
-{{#each person in people}}
-
{{person.firstName}} {{person.lastName}}
-
{{person.address}}
-{{/each}}
-```
-
-
-In preparation for further work on HTMLBars, the context switching form of `{{each}}` is deprecated. This is mostly a "mechanical" refactor and dramatically
-simplifies how to think about the context in your templates. This change should be entirely mechanical.
-
-In prior versions you may have done one of the following:
-
-```handlebars
-
- {{#each}}
- - {{name}}
- {{/each}}
-
-```
-
-```handlebars
-
- {{#each people}}
- - {{name}}
- {{/each}}
-
-```
-
-You should now be using:
-
-```handlebars
-
- {{#each person in people}}
- - {{person.name}}
- {{/each}}
-
-```
-
-### Deprecations Added in 1.10
-
-#### Deprecate beforeObservers
-
-beforeObservers are deprecated due to the negative performance implications they have for Ember internals and applications.
-
-Typically they were used to have access to the old value of a property when it's about to change, but you can get same functionality in an even more efficient way with just a few lines of code:
-
-```js
-function fooObserver(obj){
- var newFoo = obj.get('foo');
- if (obj._oldFoo !== newFoo) {
- // do your stuff here
- obj._oldFoo = newFoo;
- }
-}
-addObserver(obj, 'foo', fooObserver);
-fooObserver(obj); // Optionally call the observer immediately
-```
diff --git a/source/ember-cli/glossary.md b/source/ember-cli/glossary.md
new file mode 100644
index 000000000..60097a659
--- /dev/null
+++ b/source/ember-cli/glossary.md
@@ -0,0 +1,85 @@
+Joining a web development community can be a challenge within itself, especially when all the resources you visit assume you're familiar with other technologies that you're not familiar with.
+
+Our goal is to help you avoid that mess and come up to speed as fast as possible; you can consider us your internet friend.
+
+## CDN
+Content Delivery Network
+
+This is typically a paid service you can use to get great performance for your app. You start by uploading a resource (image, JavaScript file, etc) to a company like Akamai or CloudFlare. That uploaded resource will have an absolute URL which you can reference anywhere in your app. This URL will which resolves differently for folks depending on where they're browsing.
+
+Behind the scenes, the CDN will distribute your content geographically with the goal of end-users being able to fetch your content with the lowest latency possible. For example, if a user is in India, they'd likely get content served from India faster than from the United States.
+
+
+## CoffeeScript, TypeScript
+These are both languages which end up compiling to JavaScript; you're able to write your code using the syntax provided and when ready you compile/transpile your TypesScript or CoffeeScript into JavaScript.
+
+[CoffeeScript vs TypeScript](http://www.stoutsystems.com/articles/coffeescript-versus-typescript/)
+
+
+## Evergreen browsers
+Browsers that update themselves (without user intervention).
+
+[Evergreen Browsers](http://tomdale.net/2013/05/evergreen-browsers/)
+
+
+## ES3, ES5, ES5.1, ES6 (aka ES2015), etc
+ES stands for ECMAScript, which is the specification that JavaScript is based on. The number that follows is the version of the specification.
+
+Most browsers support at least ES5, and some even have ES6 (also known as ES2015) support. You can check each browser's support (including yours) here:
+
+* [ES5 support](http://kangax.github.io/compat-table/es5/)
+* [ES6 support](http://kangax.github.io/compat-table/es6/")
+
+[ECMAScript](https://en.wikipedia.org/wiki/ECMAScript)
+
+
+## LESS, Sass
+Both LESS and Sass are types of CSS preprocessor markup intended to give you much more control over your CSS. During the build process, the LESS or Sass resources "compile" down to vanilla CSS (which is what the end-user downloads and use in their browser).
+
+[Sass/Less Comparison](https://gist.github.com/chriseppstein/674726)
+
+
+## Linter, linting, jslint, jshint
+A validation tool which checks for common issues in your JavaScript. You'd usually use this in your build process to enforce quality in your codebase. A great example of something to check for: *making sure you've always got your semicolons*.
+
+[An example of some of the options you can configure](http://jshint.com/docs/options/)
+
+
+## Polyfill
+This is concept that typically means providing JavaScript which tests for features that are missing (prototypes not defined, etc) and "fills" them by providing an implementation.
+
+
+## Promise
+Asynchronous calls typically return a promise (or deferred). This is an object which has a state: it can be given handlers for when it's fulfilled or rejected.
+
+Ember makes use of these in places like the model hook for a route. Until the promise resolves, Ember is able to put the route into a "loading" state.
+
+[An open standard for sound, interoperable JavaScript promises](https://promisesaplus.com/)
+[emberjs.com - A word on promises](http://emberjs.com/guides/routing/asynchronous-routing/#toc_a-word-on-promises)
+
+
+## SSR
+Server Side Rendering
+
+[Inside FastBoot: The Road to Server-Side Rendering](http://emberjs.com/blog/2014/12/22/inside-fastboot-the-road-to-server-side-rendering.html)
+
+
+## Transpile
+When related to JavaScript, this can be part of your build process which "transpiles" (converts) your ES6 syntax JavaScript to JavaScript that is supported by current browsers.
+
+Besides ES6, you'll see a lot of content about compiling/transpiling CoffeeScript, a short-hand language which can "compile" to JavaScript.
+
+* Ember CLI specifically uses [Babel](https://babeljs.io/) via the [ember-cli-babel](https://github.com/babel/ember-cli-babel) plugin.
+
+
+## Shadow DOM
+**Not to be confused with Virtual DOM**. Shadow DOM is still a work in progress, but basically a proposed way to have an "isolated" DOM encapsulated within your app's DOM.
+
+Creating a re-usable "widget" or control might be a good use-case for this. Browsers implement some of their controls using their own version of a shadow DOM.
+
+* [W3C Working Draft](http://www.w3.org/TR/shadow-dom/)
+* [What the Heck is Shadow DOM?](http://glazkov.com/2011/01/14/what-the-heck-is-shadow-dom/)
+
+
+## Virtual DOM
+**Not to be confused with Shadow DOM**. The concept of a virtual DOM means abstracting your code (or in our case, Ember) away from using the browser's DOM in favor of a "virtual" DOM that can easily be accessed for read/writes or even serialized.
\ No newline at end of file
diff --git a/source/ember-cli/index.md b/source/ember-cli/index.md
new file mode 100644
index 000000000..b661124dc
--- /dev/null
+++ b/source/ember-cli/index.md
@@ -0,0 +1,58 @@
+Installing Ember is *easy*! And our new install process includes *Ember CLI*, Ember's build tool
+
+* State of the art asset management (including combining, minifying, and versioning)
+* Built-in generators can help you create components, routes, and more (and their test cases!)
+* A standard project layout. Working on other Ember apps is easy, they're organized similarly
+* Native [JavaScript modules](http://jsmodules.io/) to keep your project organized
+* A complete testing framework (unit tests, integration tests)
+* Access to a growing ecosystem of [Ember Addons](http://www.emberaddons.com/). Add functionality to your app without writing a single line of code! They're already packaged up and ready to add to your app
+
+
+## Installation
+
+Installing Ember is done using [NPM](#toc_got-node-and-npm). While you're at it we recommend you to also install phantomjs (if you don't have it already). Ember CLI uses phantomjs to run tests from the command line (without the need for a browser to be open).
+
+```bash
+npm install -g ember-cli
+npm install -g phantomjs
+```
+
+## Testing your installation
+
+At this point, you should be good to go... but we can test out your install to make sure everything works great.
+
+Let's run the generator for your project:
+
+```bash
+ember new my-app
+```
+
+This will create a new `my-app` folder and generate an application structure for you.
+
+Once the generation process finishes, let's verify that we can launch the newly created app:
+
+```bash
+cd my-app
+ember server
+```
+
+navigate to `http://localhost:4200` to see your new app in action.
+
+## Troubleshooting
+
+### Got Node (and NPM)?
+
+Node Package Manager (npm) comes bundled with node.js and makes installing easy. If you're not sure if you have node.js installed, try running the following from your command line:
+
+```bash
+node --version
+```
+
+If the command works and you get back something like 0.10.x, you've already got it installed!
+
+If you **don't** have it installed...
+
+* Windows or Mac users [can simply download and run the installer](http://nodejs.org/download/).
+* Linux users [can check out this great guide](https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager) by Joyent for install instructions.
+
+Once you've got node.js installed, re-run the above ```node --version``` to verify your install.
diff --git a/source/getting-ember/index.md b/source/getting-ember/index.md
deleted file mode 100644
index 04a56ad9b..000000000
--- a/source/getting-ember/index.md
+++ /dev/null
@@ -1,35 +0,0 @@
-##Ember Builds
-
-The Ember Release Management Team maintains a variety of ways to get Ember and Ember Data builds.
-
-###Channels
-The latest [Release](/builds#/release), [Beta](/builds#/beta), and [Canary](/builds#/canary) builds of Ember and Ember data can be found [here](/builds). For each channel a development, minified, and production version is available. For more on the different channels read the [Post 1.0 Release Cycle](/blog/2013/09/06/new-ember-release-process.html) blog post.
-
-###Tagged Releases
-Past release and beta builds of Ember and Ember Data are available at [Tagged Releases](/builds#/tagged). These builds can be useful to track down regressions in your application, but it is recommended to use the latest stable release in production.
-
-
-
-##Bower
-
-Bower is a package manager for the web. Bower makes it easy to manage dependencies in your application including Ember and Ember Data. To learn more about Bower visit [http://bower.io/](http://bower.io/).
-
-Adding Ember to your application with Bower is easy; simply run `bower install ember --save`. For Ember Data, run `bower install ember-data --save`. You can also add `ember` or `ember-data` to your `bower.json` file as follows.
-
-```json
-{
- "name": "your-app",
- "dependencies": {
- "ember": "~1.6",
- "ember-data": "~1.0.0-beta.8"
- }
-}
-
-```
-
-##RubyGems
-
-If your application uses a Ruby based build system, you can use the [ember-source](http://rubygems.org/gems/ember-source) and [ember-data-source](http://rubygems.org/gems/ember-data-source) RubyGems to access ember and ember data sources from Ruby.
-
-If your application is built in Rails, the [ember-rails](http://rubygems.org/gems/ember-rails) RubyGem makes it easy to integrate Ember into your Ruby on Rails application.
-
diff --git a/source/models/connecting-to-an-http-server.md b/source/models/connecting-to-an-http-server.md
index eaab1153c..621922edd 100644
--- a/source/models/connecting-to-an-http-server.md
+++ b/source/models/connecting-to-an-http-server.md
@@ -20,10 +20,10 @@ data is structured.
The REST adapter uses the name of the model to determine what URL to
send JSON to.
-For example, if you ask for an `App.Photo` record by ID:
+For example, if you ask for a `photo` record by ID:
-```js
-App.PhotoRoute = Ember.Route.extend({
+```app/routes/photo.js
+export default Ember.Route.extend({
model: function(params) {
return this.store.find('photo', params.photo_id);
}
@@ -52,12 +52,18 @@ REST adapter:
Given the following models:
-```js
-App.Post = DS.Model.extend({
+```app/models/post.js
+import DS from 'ember-data';
+
+export default DS.Model.extend({
title: DS.attr(),
comments: DS.hasMany('comment'),
user: DS.belongsTo('user')
});
+```
+
+```app/models/comment.js
+import DS from 'ember-data';
App.Comment = DS.Model.extend({
body: DS.attr()
@@ -90,21 +96,29 @@ To quickly prototype a model and see the expected JSON, try using the [Ember Dat
### Customizing the Adapter
-To customize the REST adapter, define a subclass of `DS.RESTAdapter` and
-name it `App.ApplicationAdapter`. You can then override its properties
+To customize the REST adapter, create a `app/adapters/application.js` file
+and export a subclass of `DS.RESTAdapter`. You can then override its properties
and methods to customize how records are retrieved and saved.
+```app/adapters/application.js
+export default DS.RESTAdapter.extend({
+ ...
+});
+```
+
#### Customizing a Specific Model
It's entirely possible that you need to define options for just one model instead of an application-wide customization. In that case, you can create an adapter named after the model you are specifying:
-```js
-App.PostAdapter = DS.RESTAdapter.extend({
+```app/adapters/post.js
+export default DS.RESTAdapter.extend({
namespace: 'api/v2',
host: 'https://api.example2.com'
});
+```
-App.PhotoAdapter = DS.RESTAdapter.extend({
+```app/adapters/photo.js
+export default DS.RESTAdapter.extend({
namespace: 'api/v1',
host: 'https://api.example.com'
});
@@ -124,8 +138,8 @@ particular person might go to `/api/v1/people/1`.
In that case, set `namespace` property to `api/v1`.
-```js
-App.ApplicationAdapter = DS.RESTAdapter.extend({
+```app/adapters/application.js
+export default DS.RESTAdapter.extend({
namespace: 'api/v1'
});
```
@@ -143,8 +157,8 @@ your server will need to be configured to send the correct CORS headers.
To change the host that requests are sent to, set the `host` property:
-```js
-App.ApplicationAdapter = DS.RESTAdapter.extend({
+```app/adapters/application.js
+export default DS.RESTAdapter.extend({
host: 'https://api.example.com'
});
```
@@ -159,8 +173,8 @@ property and Ember Data will send them along with each ajax request.
For Example
-```js
-App.ApplicationAdapter = DS.RESTAdapter.extend({
+```app/adapters/application.js
+export default DS.RESTAdapter.extend({
headers: {
'API_KEY': 'secret key',
'ANOTHER_HEADER': 'Some header value'
diff --git a/source/models/customizing-adapters.md b/source/models/customizing-adapters.md
index cf8710028..6b9c7289a 100644
--- a/source/models/customizing-adapters.md
+++ b/source/models/customizing-adapters.md
@@ -17,22 +17,24 @@ more testable, easier to understand and reduces bloat for people who
may want to subclass your adapter.
If your backend has some consistent rules you can define an
-`ApplicationAdapter`. The `ApplicationAdapter` will get priority over
+`adapter:application`. The `adapter:application` will get priority over
the default Adapter, however it will still be superseded by model
specific Adapters.
-```js
-App.ApplicationAdapter = DS.RESTAdapter.extend({
+```app/adapters/application.js
+export default DS.RESTAdapter.extend({
// Application specific overrides go here
});
```
If you have one model that has exceptional rules for communicating
with its backend than the others you can create a Model specific
-Adapter by naming an adapter "ModelName" + "Adapter".
+Adapter by running the command `ember generate adapter adapter-name`".
+For example, running `ember generate adapter post` will create the
+following file:
-```js
-App.PostAdapter = DS.RESTAdapter.extend({
+```app/adapters/post.js
+export default DS.RESTAdapter.extend({
namespace: 'api/v1'
});
```
@@ -72,13 +74,13 @@ non-standard backends.
The `namespace` property can be used to prefix requests with a
specific url namespace.
-```js
-App.ApplicationAdapter = DS.RESTAdapter.extend({
+```app/adapters/application.js
+export default DS.RESTAdapter.extend({
namespace: 'api/1'
});
```
-Requests for `App.Person` would now target `http://emberjs.com/api/1/people/1`.
+Requests for `person` would now target `http://emberjs.com/api/1/people/1`.
#### Host Customization
@@ -87,13 +89,13 @@ By default the adapter will target the current domain. If you would
like to specify a new domain you can do so by setting the `host`
property on the adapter.
-```js
-App.ApplicationAdapter = DS.RESTAdapter.extend({
+```app/adapters/application.js
+export default DS.RESTAdapter.extend({
host: 'https://api.example.com'
});
```
-Requests for `App.Person` would now target `https://api.example.com/people/1`.
+Requests for `person` would now target `https://api.example.com/people/1`.
#### Path Customization
@@ -106,16 +108,16 @@ For example, if you did not want to pluralize model names and needed
underscore_case instead of camelCase you could override the
`pathForType` method like this:
-```js
-App.ApplicationAdapter = DS.RESTAdapter.extend({
+```app/adapters/application.js
+export default DS.RESTAdapter.extend({
pathForType: function(type) {
return Ember.String.underscore(type);
}
});
```
-Requests for `App.Person` would now target `/person/1`.
-Requests for `App.UserProfile` would now target `/user_profile/1`.
+Requests for `person` would now target `/person/1`.
+Requests for `userProfile` would now target `/user_profile/1`.
#### Authoring Adapters
@@ -129,8 +131,8 @@ adapter it is important to remember to set this property to ensure
Ember does the right thing in the case a user of your adapter
does not specify an `ApplicationSerializer`.
-```js
-MyCustomAdapterAdapter = DS.RESTAdapter.extend({
+```app/adapters/my-custom-adapter.js
+export default DS.RESTAdapter.extend({
defaultSerializer: '-default'
});
```
diff --git a/source/models/defining-models.md b/source/models/defining-models.md
index 663f5fbd5..35ab576a6 100644
--- a/source/models/defining-models.md
+++ b/source/models/defining-models.md
@@ -12,8 +12,8 @@ Make sure to include `ember-data.js` after `ember.js`
For every model in your application, create a subclass of `DS.Model`:
-```javascript
-App.Person = DS.Model.extend();
+```app/models/person.js
+export default DS.Model.extend();
```
After you have defined a model class, you can start finding and creating
@@ -26,7 +26,7 @@ type of record to find:
store.find('person', 1);
```
-The table below shows how model names map to model classes.
+The table below shows how model names map to model file paths.
@@ -37,11 +37,11 @@ The table below shows how model names map to model classes.
photo |
- App.Photo |
+ app/models/photo.js |
- adminUserProfile |
- App.AdminUserProfile |
+ admin-user-profile |
+ app/models/admin-user-profile.js |
@@ -49,13 +49,11 @@ The table below shows how model names map to model classes.
You can specify which attributes a model has by using `DS.attr`.
-```javascript
-var attr = DS.attr;
-
-App.Person = DS.Model.extend({
- firstName: attr(),
- lastName: attr(),
- birthday: attr()
+```app/models/person.js
+export default DS.Model.extend({
+ firstName: DS.attr(),
+ lastName: DS.attr(),
+ birthday: DS.attr()
});
```
@@ -67,10 +65,8 @@ You can use attributes just like any other property, including as part of a
computed property. Frequently, you will want to define computed
properties that combine or transform primitive attributes.
-```javascript
-var attr = DS.attr;
-
-App.Person = DS.Model.extend({
+```app/models/person.js
+export default DS.Model.extend({
firstName: attr(),
lastName: attr(),
@@ -87,8 +83,8 @@ If you don't specify the type of the attribute, it will be whatever was
provided by the server. You can make sure that an attribute is always
coerced into a particular type by passing a `type` to `attr`:
-```js
-App.Person = DS.Model.extend({
+```app/models/person.js
+export default DS.Model.extend({
birthday: DS.attr('date')
});
```
@@ -111,14 +107,12 @@ attribute types, and new types can be registered as transforms. See the
Example
- ```JavaScript
- var attr = DS.attr;
-
- App.User = DS.Model.extend({
- username: attr('string'),
- email: attr('string'),
- verified: attr('boolean', {defaultValue: false}),
- createdAt: attr('string', {
+ ```app/models/user.js
+ export default DS.Model.extend({
+ username: DS.attr('string'),
+ email: DS.attr('string'),
+ verified: DS.attr('boolean', {defaultValue: false}),
+ createdAt: DS.attr('string', {
defaultValue: function() { return new Date(); }
})
});
@@ -135,12 +129,14 @@ define how your models relate to each other.
To declare a one-to-one relationship between two models, use
`DS.belongsTo`:
-```js
-App.User = DS.Model.extend({
+```app/models/user.js
+export default DS.Model.extend({
profile: DS.belongsTo('profile')
});
+```
-App.Profile = DS.Model.extend({
+```app/models/profile.js
+export default DS.Model.extend({
user: DS.belongsTo('user')
});
```
@@ -150,12 +146,14 @@ App.Profile = DS.Model.extend({
To declare a one-to-many relationship between two models, use
`DS.belongsTo` in combination with `DS.hasMany`, like this:
-```js
-App.Post = DS.Model.extend({
+```app/models/post.js
+export default DS.Model.extend({
comments: DS.hasMany('comment')
});
+```
-App.Comment = DS.Model.extend({
+```app/models/comment.js
+export default DS.Model.extend({
post: DS.belongsTo('post')
});
```
@@ -165,12 +163,13 @@ App.Comment = DS.Model.extend({
To declare a many-to-many relationship between two models, use
`DS.hasMany`:
-```js
-App.Post = DS.Model.extend({
+```app/models/post.js
+export default DS.Model.extend({
tags: DS.hasMany('tag')
});
-App.Tag = DS.Model.extend({
+```app/models/tag.js
+export default DS.Model.extend({
posts: DS.hasMany('post')
});
```
@@ -187,20 +186,18 @@ However, sometimes you may have multiple `belongsTo`/`hasMany`s for the
same type. You can specify which property on the related model is the
inverse using `DS.hasMany`'s `inverse` option:
-```javascript
-var belongsTo = DS.belongsTo,
- hasMany = DS.hasMany;
-
-App.Comment = DS.Model.extend({
- onePost: belongsTo('post'),
- twoPost: belongsTo('post'),
- redPost: belongsTo('post'),
- bluePost: belongsTo('post')
+```app/models/comment.js
+export default DS.Model.extend({
+ onePost: DS.belongsTo('post'),
+ twoPost: DS.belongsTo('post'),
+ redPost: DS.belongsTo('post'),
+ bluePost: DS.belongsTo('post')
});
+```
-
-App.Post = DS.Model.extend({
- comments: hasMany('comment', {
+```app/models/post.js
+export default DS.Model.extend({
+ comments: DS.hasMany('comment', {
inverse: 'redPost'
})
});
@@ -214,23 +211,17 @@ When you want to define a reflexive relation, you must either explicitly define
the other side, and set the explicit inverse accordingly, and if you don't need the
other side, set the inverse to null.
-```javascript
-var belongsTo = DS.belongsTo,
- hasMany = DS.hasMany;
-
-App.Folder = DS.Model.extend({
- children: hasMany('folder', {inverse: 'parent'}),
- parent: belongsTo('folder', {inverse: 'children'})
+```app/models/folder.js
+export default DS.Model.extend({
+ children: DS.hasMany('folder', {inverse: 'parent'}),
+ parent: DS.belongsTo('folder', {inverse: 'children'})
});
```
or
-```javascript
-var belongsTo = DS.belongsTo,
-
-App.Folder = DS.Model.extend({
+```app/models/folder.js
+export default DS.Model.extend({
parent: belongsTo('folder', {inverse: null})
});
```
-
diff --git a/source/models/finding-records.md b/source/models/finding-records.md
index db1091a0c..78842f18c 100644
--- a/source/models/finding-records.md
+++ b/source/models/finding-records.md
@@ -67,19 +67,27 @@ This makes it easy to write apps with asynchronous data using Ember
Data. Just return the requested record from the `model` hook, and let
Ember deal with figuring out whether a network request is needed or not.
-```javascript
+```app/router.js
+var Router = Ember.Router.extend({});
+
App.Router.map(function() {
this.resource('posts');
this.resource('post', { path: ':post_id' });
});
-App.PostsRoute = Ember.Route.extend({
+export default Router;
+```
+
+```app/routes/posts.js
+export default Ember.Route.extend({
model: function() {
return this.store.find('post');
}
});
+```
-App.PostRoute = Ember.Route.extend({
+```app/routes/post.js
+export default Ember.Route.extend({
model: function(params) {
return this.store.find('post', params.post_id);
}
diff --git a/source/models/frequently-asked-questions.md b/source/models/frequently-asked-questions.md
index a7a093963..a6bc5d9c9 100644
--- a/source/models/frequently-asked-questions.md
+++ b/source/models/frequently-asked-questions.md
@@ -64,8 +64,8 @@ This will offload searching all of the possible records to the server,
while still creating a live updating list that includes records created
and modified on the client.
-```js
-App.PostsFavoritedRoute = Ember.Route.extend({
+```app/routes/posts/favourited.js
+export default Ember.Route.extend({
model: function() {
var store = this.store;
diff --git a/source/models/handling-metadata.md b/source/models/handling-metadata.md
index 399ea8612..3ab533405 100644
--- a/source/models/handling-metadata.md
+++ b/source/models/handling-metadata.md
@@ -58,8 +58,8 @@ You can also customize metadata extraction by overriding the `extractMeta` metho
You could extract it like so:
-```js
-App.ApplicationSerializer = DS.RESTSerializer.extend({
+```app/serializers/application.js
+export default DS.RESTSerializer.extend({
extractMeta: function(store, type, payload) {
if (payload && payload.total) {
store.setMetadataFor(type, { total: payload.total }); // sets the metadata for "post"
diff --git a/source/models/index.md b/source/models/index.md
index d3e7bf291..1a4897483 100644
--- a/source/models/index.md
+++ b/source/models/index.md
@@ -33,18 +33,13 @@ Ember Data is also designed to work with streaming APIs like
socket.io, Firebase, or WebSockets. You can open a socket to your server
and push changes to records into the store whenever they occur.
-Currently, Ember Data ships as a separate library from Ember.js. Until
-Ember Data is included as part of the standard distribution, you can get
-a copy of the latest passing build from
-[emberjs.com/builds][builds]:
+Currently, projects generated by `ember-cli` include Ember Data as a
+dependency in both `package.json` and `bower.json`. If you do not wish
+to use Ember Data, run the following command:
-* [Development][development-build]
-* [Minified][minified-build]
-
-[emberdata]: https://github.com/emberjs/data
-[builds]: /builds
-[development-build]: http://builds.emberjs.com/canary/ember-data.js
-[minified-build]: http://builds.emberjs.com/canary/ember-data.min.js
+```bash
+$ npm rm ember-data --save-dev
+```
### Core Concepts
@@ -63,11 +58,11 @@ This instance of `DS.Store` is created for you automatically and is shared
among all of the objects in your application.
You will use the store to retrieve records, as well to create new ones.
-For example, we might want to find an `App.Person` model with the ID of
+For example, we might want to find a `person` with the ID of
`1` from our route's `model` hook:
-```js
-App.IndexRoute = Ember.Route.extend({
+```app/routes/index.js
+export default Ember.Route.extend({
model: function() {
return this.store.find('person', 1);
}
@@ -82,8 +77,8 @@ if they leave your app and come back later (or if they refresh the page)
should be represented by a model.
For example, if you were writing a web application for placing orders at
-a restaurant, you might have models like `Order`, `LineItem`, and
-`MenuItem`.
+a restaurant, you might have models like `order`, `line-item`, and
+`menu-item`.
Fetching orders becomes very easy:
@@ -95,23 +90,25 @@ Models define the type of data that will be provided by your server. For
example, a `Person` model might have a `firstName` attribute that is a
string, and a `birthday` attribute that is a date:
-```js
-App.Person = DS.Model.extend({
+```app/models/person.js
+export default DS.Model.extend({
firstName: DS.attr('string'),
birthday: DS.attr('date')
});
```
A model also describes its relationships with other objects. For
-example, an `Order` may have many `LineItems`, and a `LineItem` may
-belong to a particular `Order`.
+example, an `order` may have many `line-items`, and a
+`line-item` may belong to a particular `order`.
-```js
-App.Order = DS.Model.extend({
+```app/models/order.js
+export default DS.Model.extend({
lineItems: DS.hasMany('lineItem')
});
+```
-App.LineItem = DS.Model.extend({
+```app/models/line-item.js
+export default DS.Model.extend({
order: DS.belongsTo('order')
});
```
@@ -128,8 +125,8 @@ to the server.
A record is uniquely identified by its model type and id.
For example, if you were writing a contact management app, you might
-have a model called `Person`. An individual record in your app might
-have a type of `Person` and an ID of `1` or `steve-buscemi`.
+have a `person`. An individual record in your app might
+have a type of `person` and an ID of `1` or `steve-buscemi`.
```js
this.store.find('person', 1); // => { id: 1, name: 'steve-buscemi' }
diff --git a/source/models/pushing-records-into-the-store.md b/source/models/pushing-records-into-the-store.md
index ea747a790..441c4fe7a 100644
--- a/source/models/pushing-records-into-the-store.md
+++ b/source/models/pushing-records-into-the-store.md
@@ -24,20 +24,20 @@ To push a record into the store, call the store's `push()` method.
For example, imagine we want to preload some data into the store when
the application boots for the first time.
-We can use the `ApplicationRoute` to do so. The `ApplicationRoute` is
+We can use the `route:application` to do so. The `route:application` is
the top-most route in the route hierarchy, and its `model` hook gets
called once when the app starts up.
-```js
-var attr = DS.attr;
-
-App.Album = DS.Model.extend({
- title: attr(),
- artist: attr(),
- songCount: attr()
+```app/models/album.js
+export default DS.Model.extend({
+ title: DS.attr(),
+ artist: DS.attr(),
+ songCount: DS.attr()
});
+```
-App.ApplicationRoute = Ember.Route.extend({
+```app/routes/application.js
+export default Ember.Route.extend({
model: function() {
this.store.push('album', {
id: 1,
diff --git a/source/models/the-basic-adapter.md b/source/models/the-basic-adapter.md
index 5107c5c95..79253e1ee 100644
--- a/source/models/the-basic-adapter.md
+++ b/source/models/the-basic-adapter.md
@@ -8,16 +8,18 @@ then load the data returned into the store.
You provide the hooks to Ember Data by implementing a `sync` object on
each model:
-```javascript
-App.Person = DS.Model.extend({
+```app/models/person.js
+var Person = DS.Model.extend({
//...model definition...
});
-App.Person.sync = {
+Person.sync = {
find: function(id, process) {
// ...
}
};
+
+export default Person
```
### Finding Records
@@ -48,8 +50,8 @@ Ember Data expects that the JSON you load in will have keys with the
same name as the attributes and relationships that you have defined in
the model. For example, if you have a `Person` model:
-```javascript
-App.Person = DS.Model.extend({
+```app/models/person.js
+export default DS.Model.extend({
firstName: DS.attr('string'),
lastName: DS.attr('string'),
age: DS.attr('number')
diff --git a/source/models/the-fixture-adapter.md b/source/models/the-fixture-adapter.md
index c4582a5b8..cc1263f23 100644
--- a/source/models/the-fixture-adapter.md
+++ b/source/models/the-fixture-adapter.md
@@ -27,8 +27,8 @@ You should refer to [Defining a Model][1] for a more in-depth guide on using
Ember Data Models, but for the purposes of demonstration we'll use an example
modeling people who document Ember.js.
-```JavaScript
-App.Documenter = DS.Model.extend({
+```app/models/documenter.js
+export default DS.Model.extend({
firstName: DS.attr( 'string' ),
lastName: DS.attr( 'string' )
});
@@ -39,20 +39,27 @@ App.Documenter = DS.Model.extend({
In order to attach fixtures to your model, you have to use `reopenClass` method and define
fixtures:
-```JavaScript
-App.Documenter.reopenClass({
+```app/models/documenter.js
+let Documenter = DS.Model.extend({
+ firstName: DS.attr( 'string' ),
+ lastName: DS.attr( 'string' )
+});
+
+Documenter.reopenClass({
FIXTURES: [
{ id: 1, firstName: 'Trek', lastName: 'Glowacki' },
{ id: 2, firstName: 'Tom' , lastName: 'Dale' }
]
});
+
+export default Documenter
```
That's it! You can now use all of methods for [Finding Records][2] in your
application. For example:
-```JavaScript
-App.DocumenterRoute = Ember.Route.extend({
+```app/routes/documenter.js
+export default Ember.Route.extend({
model: function() {
return this.store.find('documenter', 1); // returns a promise that will resolve
// with the record representing Trek Glowacki
diff --git a/source/models/the-rest-adapter.md b/source/models/the-rest-adapter.md
index 97f3ff290..8a45983a1 100644
--- a/source/models/the-rest-adapter.md
+++ b/source/models/the-rest-adapter.md
@@ -45,7 +45,7 @@ inflector.irregular('formula', 'formulae');
inflector.uncountable('advice');
```
-This will tell the REST adapter that requests for `App.Formula` requests
+This will tell the REST adapter that requests for `formula`
should go to `/formulae/1` instead of `/formulas/1`.
#### Endpoint Path Customization
@@ -53,25 +53,25 @@ should go to `/formulae/1` instead of `/formulas/1`.
Endpoint paths can be prefixed with a namespace by setting the `namespace`
property on the adapter:
-```js
-App.ApplicationAdapter = DS.RESTAdapter.extend({
+```app/adapters/application.js
+export default DS.RESTAdapter.extend({
namespace: 'api/1'
});
```
-Requests for `App.Person` would now target `http://emberjs.com/api/1/people/1`.
+Requests for `person` would now target `http://emberjs.com/api/1/people/1`.
#### Host Customization
An adapter can target other hosts by setting the `host` property.
-```js
-App.ApplicationAdapter = DS.RESTAdapter.extend({
+```app/adapters/application.js
+export default DS.RESTAdapter.extend({
host: 'https://api.example.com'
});
```
-Requests for `App.Person` would now target `https://api.example.com/people/1`.
+Requests for `person` would now target `https://api.example.com/people/1`.
### JSON Conventions
@@ -111,8 +111,8 @@ extractDeleteRecord: function(store, type, payload) {
Attribute names should be camelized. For example, if you have a model like this:
-```js
-App.Person = DS.Model.extend({
+```app/models/person.js
+export default DS.Model.extend({
firstName: DS.attr('string'),
lastName: DS.attr('string'),
@@ -133,16 +133,18 @@ The JSON returned from your server should look like this:
```
Irregular keys can be mapped with a custom serializer. If the JSON for
-the `Person` model has a key of `lastNameOfPerson`, and the desired
+`person` has a key of `lastNameOfPerson`, and the desired
attribute name is simply `lastName`, then create a custom Serializer
for the model and override the `normalizeHash` property.
-```js
-App.Person = DS.Model.extend({
+```app/models/person.js
+export default DS.Model.extend({
lastName: DS.attr('string')
});
+```
-App.PersonSerializer = DS.RESTSerializer.extend({
+```app/serializers/person.js
+export default DS.RESTSerializer.extend({
normalizeHash: {
lastNameOfPerson: function(hash) {
hash.lastName = hash.lastNameOfPerson;
@@ -159,8 +161,8 @@ App.PersonSerializer = DS.RESTSerializer.extend({
References to other records should be done by ID. For example, if you
have a model with a `hasMany` relationship:
-```js
-App.Post = DS.Model.extend({
+```app/models/post.js
+export default DS.Model.extend({
comments: DS.hasMany('comment', {async: true})
});
```
@@ -182,8 +184,8 @@ Any `belongsTo` relationships in the JSON representation should be the
camelized version of the Ember Data model's name, with the string
`Id` appended. For example, if you have a model:
-```js
-App.Comment = DS.Model.extend({
+```app/models/comment.js
+export default DS.Model.extend({
post: DS.belongsTo('post')
});
```
@@ -201,13 +203,13 @@ The JSON should encode the relationship as an ID to another record:
If needed these naming conventions can be overwritten by implementing
the `keyForRelationship` method.
-```js
- App.ApplicationSerializer = DS.RESTSerializer.extend({
- keyForRelationship: function(key, relationship) {
- return key + 'Ids';
- }
- });
- ```
+```app/serializers/application.js
+export default DS.RESTSerializer.extend({
+ keyForRelationship: function(key, relationship) {
+ return key + 'Ids';
+ }
+});
+```
#### Sideloaded Relationships
@@ -247,8 +249,8 @@ server may return a non-standard date format.
Ember Data can have new JSON transforms
registered for use as attributes:
-```js
-App.CoordinatePointTransform = DS.Transform.extend({
+```app/transforms/coordinate-point.js
+export default DS.Transform.extend({
serialize: function(value) {
return [value.get('x'), value.get('y')];
},
@@ -256,8 +258,10 @@ App.CoordinatePointTransform = DS.Transform.extend({
return Ember.create({ x: value[0], y: value[1] });
}
});
+```
-App.Cursor = DS.Model.extend({
+```app/models/cursor.js
+export default DS.Model.extend({
position: DS.attr('coordinatePoint')
});
```
diff --git a/source/object-model/classes-and-instances.md b/source/object-model/classes-and-instances.md
index 57834529e..37a09ed09 100644
--- a/source/object-model/classes-and-instances.md
+++ b/source/object-model/classes-and-instances.md
@@ -2,21 +2,21 @@ To define a new Ember _class_, call the `extend()` method on
`Ember.Object`:
```javascript
-App.Person = Ember.Object.extend({
+Person = Ember.Object.extend({
say: function(thing) {
alert(thing);
}
});
```
-This defines a new `App.Person` class with a `say()` method.
+This defines a new `Person` class with a `say()` method.
You can also create a _subclass_ from any existing class by calling
its `extend()` method. For example, you might want to create a subclass
of Ember's built-in `Ember.View` class:
-```js
-App.PersonView = Ember.View.extend({
+```app/views/person.js
+PersonView = Ember.View.extend({
tagName: 'li',
classNameBindings: ['isAdministrator']
});
@@ -27,20 +27,20 @@ implementation of your parent class by calling the special `_super()`
method:
```javascript
-App.Person = Ember.Object.extend({
+Person = Ember.Object.extend({
say: function(thing) {
var name = this.get('name');
alert(name + " says: " + thing);
}
});
-App.Soldier = App.Person.extend({
+Soldier = Person.extend({
say: function(thing) {
this._super(thing + ", sir!");
}
});
-var yehuda = App.Soldier.create({
+var yehuda = Soldier.create({
name: "Yehuda Katz"
});
@@ -55,7 +55,7 @@ computed properties you defined on the class will be available to
instances:
```javascript
-var person = App.Person.create();
+var person = Person.create();
person.say("Hello"); // alerts " says: Hello"
```
@@ -63,13 +63,13 @@ When creating an instance, you can initialize the value of its properties
by passing an optional hash to the `create()` method:
```javascript
-App.Person = Ember.Object.extend({
+Person = Ember.Object.extend({
helloWorld: function() {
alert("Hi, my name is " + this.get('name'));
}
});
-var tom = App.Person.create({
+var tom = Person.create({
name: "Tom Dale"
});
@@ -84,8 +84,8 @@ properties, create a new subclass and instantiate that.
By convention, properties or variables that hold classes are
PascalCased, while instances are not. So, for example, the variable
-`App.Person` would point to a class, while `person` would point to an instance
-(usually of the `App.Person` class). You should stick to these naming
+`Person` would point to a class, while `person` would point to an instance
+(usually of the `Person` class). You should stick to these naming
conventions in your Ember applications.
### Initializing Instances
@@ -95,14 +95,14 @@ automatically. This is the ideal place to do setup required on new
instances:
```js
-App.Person = Ember.Object.extend({
+Person = Ember.Object.extend({
init: function() {
var name = this.get('name');
alert(name + ", reporting for duty!");
}
});
-App.Person.create({
+Person.create({
name: "Stefan Penner"
});
@@ -119,7 +119,7 @@ When accessing the properties of an object, use the `get`
and `set` accessor methods:
```js
-var person = App.Person.create();
+var person = Person.create();
var name = person.get('name');
person.set('name', "Tobias Fünke");
diff --git a/source/object-model/computed-properties-and-aggregate-data.md b/source/object-model/computed-properties-and-aggregate-data.md
index 62ae7a91e..04b8d9b8d 100644
--- a/source/object-model/computed-properties-and-aggregate-data.md
+++ b/source/object-model/computed-properties-and-aggregate-data.md
@@ -4,8 +4,8 @@ todo items in a controller to determine how many of them are completed.
Here's what that computed property might look like:
-```javascript
-App.TodosController = Ember.Controller.extend({
+```app/controllers/todos.js
+export default Ember.Controller.extend({
todos: [
Ember.Object.create({ isDone: true }),
Ember.Object.create({ isDone: false }),
@@ -31,8 +31,9 @@ this computed property when one of the following four events occurs:
In the example above, the `remaining` count is `1`:
```javascript
-App.todosController = App.TodosController.create();
-App.todosController.get('remaining');
+import TodosController from 'app/controllers/todos';
+todosController = TodosController.create();
+todosController.get('remaining');
// 1
```
@@ -40,17 +41,17 @@ If we change the todo's `isDone` property, the `remaining` property is updated
automatically:
```javascript
-var todos = App.todosController.get('todos');
+var todos = todosController.get('todos');
var todo = todos.objectAt(1);
todo.set('isDone', true);
-App.todosController.get('remaining');
+todosController.get('remaining');
// 0
todo = Ember.Object.create({ isDone: false });
todos.pushObject(todo);
-App.todosController.get('remaining');
+todosController.get('remaining');
// 1
```
diff --git a/source/object-model/computed-properties.md b/source/object-model/computed-properties.md
index 4545130d9..9658549c6 100644
--- a/source/object-model/computed-properties.md
+++ b/source/object-model/computed-properties.md
@@ -9,7 +9,7 @@ It's super handy for taking one or more normal properties and transforming or ma
We'll start with a simple example:
```javascript
-App.Person = Ember.Object.extend({
+Person = Ember.Object.extend({
// these will be supplied by `create`
firstName: null,
lastName: null,
@@ -19,7 +19,7 @@ App.Person = Ember.Object.extend({
}.property('firstName', 'lastName')
});
-var ironMan = App.Person.create({
+var ironMan = Person.create({
firstName: "Tony",
lastName: "Stark"
});
@@ -45,7 +45,7 @@ At this point, you might be wondering how you are able to call the `.property` f
You can use computed properties as values to create new computed properties. Let's add a `description` computed property to the previous example, and use the existing `fullName` property and add in some other properties:
```javascript
-App.Person = Ember.Object.extend({
+Person = Ember.Object.extend({
firstName: null,
lastName: null,
age: null,
@@ -60,7 +60,7 @@ App.Person = Ember.Object.extend({
}.property('fullName', 'age', 'country')
});
-var captainAmerica = App.Person.create({
+var captainAmerica = Person.create({
firstName: 'Steve',
lastName: 'Rogers',
age: 80,
@@ -89,7 +89,7 @@ Setting any dependent property will propagate changes through any computed prope
You can also define what Ember should do when setting a computed property. If you try to set a computed property, it will be invoked with the key (property name), the value you want to set it to, and the previous value.
```javascript
-App.Person = Ember.Object.extend({
+Person = Ember.Object.extend({
firstName: null,
lastName: null,
@@ -107,7 +107,7 @@ App.Person = Ember.Object.extend({
});
-var captainAmerica = App.Person.create();
+var captainAmerica = Person.create();
captainAmerica.set('fullName', "William Burnside");
captainAmerica.get('firstName'); // William
captainAmerica.get('lastName'); // Burnside
diff --git a/source/object-model/observers.md b/source/object-model/observers.md
index c04f0aecc..74f3ce92d 100644
--- a/source/object-model/observers.md
+++ b/source/object-model/observers.md
@@ -93,7 +93,7 @@ cannot rely on the side effect of set. Instead, specify that the observer
should also run after init by using `.on('init')`:
```javascript
-App.Person = Ember.Object.extend({
+Person = Ember.Object.extend({
init: function() {
this.set('salutation', "Mr/Ms");
},
diff --git a/source/routing/asynchronous-routing.md b/source/routing/asynchronous-routing.md
index 8a6a5bd6c..5a221a836 100644
--- a/source/routing/asynchronous-routing.md
+++ b/source/routing/asynchronous-routing.md
@@ -11,7 +11,7 @@ value). The way to retrieve this eventual value, or handle the cases
when the promise rejects, is via the promise's `then` method, which
accepts two optional callbacks, one for fulfillment and one for
rejection. If the promise fulfills, the fulfillment handler gets called
-with the fulfilled value as its sole argument, and if the promise rejects,
+with the fulfilled value as its sole argument, and if the promise rejects,
the rejection handler gets called with a reason for the rejection as its
sole argument. For example:
@@ -44,7 +44,7 @@ usernamesPromise.then(fetchPhotosOfUsers)
In the above example, if any of the methods
`fetchPhotosOfUsers`, `applyInstagramFilters`, or
-`uploadTrendyPhotoAlbum` returns a promise that rejects,
+`uploadTrendyPhotoAlbum` returns a promise that rejects,
`handleErrors` will be called with
the reason for the failure. In this manner, promises approximate an
asynchronous form of try-catch statements that prevent the rightward
@@ -53,18 +53,18 @@ approach to managing complex asynchronous logic in your applications.
This guide doesn't intend to fully delve into all the different ways
promises can be used, but if you'd like a more thorough introduction,
-take a look at the readme for [RSVP](https://github.com/tildeio/rsvp.js),
-the promise library that Ember uses.
+take a look at the readme for [RSVP](https://github.com/tildeio/rsvp.js),
+the promise library that Ember uses.
### The Router Pauses for Promises
When transitioning between routes, the Ember router collects all of the
models (via the `model` hook) that will be passed to the route's
controllers at the end of the transition. If the `model` hook (or the related
-`beforeModel` or `afterModel` hooks) return normal (non-promise) objects or
-arrays, the transition will complete immediately. But if the `model` hook
-(or the related `beforeModel` or `afterModel` hooks) returns a promise (or
-if a promise was provided as an argument to `transitionTo`), the transition
+`beforeModel` or `afterModel` hooks) return normal (non-promise) objects or
+arrays, the transition will complete immediately. But if the `model` hook
+(or the related `beforeModel` or `afterModel` hooks) returns a promise (or
+if a promise was provided as an argument to `transitionTo`), the transition
will pause until that promise fulfills or rejects.
**Note:** The router considers any object with a `then` method
@@ -78,15 +78,15 @@ will be the fulfilled values from the promises.
A basic example:
-```js
-App.TardyRoute = Ember.Route.extend({
+```app/routes/tardy.js
+export default Ember.Route.extend({
model: function() {
return new Ember.RSVP.Promise(function(resolve) {
Ember.run.later(function() {
resolve({ msg: "Hold Your Horses" });
}, 3000);
});
- },
+ },
setupController: function(controller, model) {
console.log(model.msg); // "Hold Your Horses"
@@ -94,19 +94,19 @@ App.TardyRoute = Ember.Route.extend({
});
```
-When transitioning into `TardyRoute`, the `model` hook will be called and
+When transitioning into `route:tardy`, the `model` hook will be called and
return a promise that won't resolve until 3 seconds later, during which time
the router will be paused in mid-transition. When the promise eventually
fulfills, the router will continue transitioning and eventually call
-`TardyRoute`'s `setupController` hook with the resolved object.
+`route:tardy`'s `setupController` hook with the resolved object.
This pause-on-promise behavior is extremely valuable for when you need
to guarantee that a route's data has fully loaded before displaying a
-new template.
+new template.
### When Promises Reject...
-We've covered the case when a model promise fulfills, but what if it rejects?
+We've covered the case when a model promise fulfills, but what if it rejects?
By default, if a model promise rejects during a transition, the transition is
aborted, no new destination route templates are rendered, and an error
@@ -114,12 +114,12 @@ is logged to the console.
You can configure this error-handling logic via the `error` handler on
the route's `actions` hash. When a promise rejects, an `error` event
-will be fired on that route and bubble up to `ApplicationRoute`'s
+will be fired on that route and bubble up to `route:application`'s
default error handler unless it is handled by a custom error handler
along the way, e.g.:
-```js
-App.GoodForNothingRoute = Ember.Route.extend({
+```app/routes/good-for-nothing.js
+export default Ember.Route.extend({
model: function() {
return Ember.RSVP.reject("FAIL");
},
@@ -139,18 +139,18 @@ App.GoodForNothingRoute = Ember.Route.extend({
```
In the above example, the error event would stop right at
-`GoodForNothingRoute`'s error handler and not continue to bubble. To
-make the event continue bubbling up to `ApplicationRoute`, you can
+`route:good-for-nothing`'s error handler and not continue to bubble. To
+make the event continue bubbling up to `route:application`, you can
return true from the error handler.
### Recovering from Rejection
Rejected model promises halt transitions, but because promises are chainable,
-you can catch promise rejects within the `model` hook itself and convert
+you can catch promise rejects within the `model` hook itself and convert
them into fulfills that won't halt the transition.
-```js
-App.FunkyRoute = Ember.Route.extend({
+```app/routes/funky.js
+export default Ember.Route.extend({
model: function() {
return iHopeThisWorks().then(null, function() {
// Promise rejected, fulfill with some default value to
@@ -167,7 +167,7 @@ The `model` hook covers many use cases for pause-on-promise transitions,
but sometimes you'll need the help of the related hooks `beforeModel`
and `afterModel`. The most common reason for this is that if you're
transitioning into a route with a dynamic URL segment via `{{link-to}}` or
-`transitionTo` (as opposed to a transition caused by a URL change),
+`transitionTo` (as opposed to a transition caused by a URL change),
the model for the route you're transitioning into will have already been
specified (e.g. `{{#link-to 'article' article}}` or
`this.transitionTo('article', article)`), in which case the `model` hook
@@ -194,10 +194,10 @@ The following is a far-from-exhaustive list of use cases in which
potentially wasteful server query in `model`
- Ensuring that the user has an authentication token before proceeding
onward to `model`
-- Loading application code required by this route
+- Loading application code required by this route
-```js
-App.SecretArticlesRoute = Ember.Route.extend({
+```app/routes/secret-articles.js
+export default Ember.Route.extend({
beforeModel: function() {
if (!this.controllerFor('auth').get('isLoggedIn')) {
this.transitionTo('login');
@@ -212,12 +212,12 @@ App.SecretArticlesRoute = Ember.Route.extend({
The `afterModel` hook is called after a route's model (which might be a
promise) is resolved, and follows the same pause-on-promise semantics as
-`model` and `beforeModel`. It is passed the already-resolved model
+`model` and `beforeModel`. It is passed the already-resolved model
and can therefore perform any additional logic that
depends on the fully resolved value of a model.
-```js
-App.ArticlesRoute = Ember.Route.extend({
+```app/routes/articles.js
+export default Ember.Route.extend({
model: function() {
// `this.store.find('article')` returns a promise-like object
// (it has a `then` method that can be used like a promise)
@@ -233,7 +233,7 @@ App.ArticlesRoute = Ember.Route.extend({
You might be wondering why we can't just put the `afterModel` logic
into the fulfill handler of the promise returned from `model`; the
-reason, as mentioned above, is that transitions initiated
+reason, as mentioned above, is that transitions initiated
via `{{link-to}}` or `transitionTo` likely already provided the
model for this route, so `model` wouldn't be called in these cases.
@@ -243,4 +243,3 @@ model for this route, so `model` wouldn't be called in these cases.
- [Embercasts: Client-side Authentication Part 2](http://www.embercasts.com/episodes/client-side-authentication-part-2)
- [RC6 Blog Post describing these new features](/blog/2013/06/23/ember-1-0-rc6.html)
-
diff --git a/source/routing/defining-your-routes.md b/source/routing/defining-your-routes.md
index fdcfa0a26..34769cb18 100644
--- a/source/routing/defining-your-routes.md
+++ b/source/routing/defining-your-routes.md
@@ -10,8 +10,8 @@ calling `map`, you should pass a function that will be invoked with the value
[routes](http://emberjs.com/guides/routing/defining-your-routes/) and
[resources](http://emberjs.com/guides/routing/defining-your-routes/#toc_resources).
-```javascript
-App.Router.map(function() {
+```app/router.js
+Router.map(function() {
this.route('about', { path: '/about' });
this.route('favorites', { path: '/favs' });
});
@@ -20,15 +20,15 @@ App.Router.map(function() {
Now, when the user visits `/about`, Ember.js will render the `about`
template. Visiting `/favs` will render the `favorites` template.
-**Heads up!** You get a few routes for free: the `ApplicationRoute` and
-the `IndexRoute` (corresponding to the `/` path).
+**Heads up!** You get a few routes for free: the `route:application` and
+`route:index` (corresponding to the `/` path).
[See below](#toc_initial-routes) for more details.
Note that you can leave off the path if it is the same as the route
name. In this case, the following is equivalent to the above example:
-```javascript
-App.Router.map(function() {
+```app/router.js
+Router.map(function() {
this.route('about');
this.route('favorites', { path: '/favs' });
});
@@ -52,10 +52,10 @@ points to the currently active route.
You can customize the behavior of a route by creating an `Ember.Route`
subclass. For example, to customize what happens when your user visits
-`/`, create an `App.IndexRoute`:
+`/`, create an `route:index`:
-```javascript
-App.IndexRoute = Ember.Route.extend({
+```app/routes/index.js
+export default Ember.Route.extend({
setupController: function(controller) {
// Set the IndexController's `title`
controller.set('title', 'My App');
@@ -63,7 +63,7 @@ App.IndexRoute = Ember.Route.extend({
});
```
-The `IndexController` is the starting context for the `index` template.
+`controller:index` is the starting context for the `index` template.
Now that you've set `title`, you can use it in the template:
```handlebars
@@ -71,7 +71,7 @@ Now that you've set `title`, you can use it in the template:
{{title}}
```
-(If you don't explicitly define an `App.IndexController`, Ember.js will
+(If you don't explicitly define an `controller:index`, Ember.js will
automatically generate one for you.)
Ember.js automatically figures out the names of the routes and controllers based on
@@ -90,22 +90,22 @@ the name you pass to `this.route`.
/ |
index |
- IndexController |
- IndexRoute |
+ app/controllers/index |
+ app/routes/index |
index |
/about |
about |
- AboutController |
- AboutRoute |
+ app/controllers/about |
+ app/routes/about |
about |
/favs |
favorites |
- FavoritesController |
- FavoritesRoute |
+ app/controllers/favorites |
+ app/routes/favorites |
favorites |
@@ -114,8 +114,8 @@ the name you pass to `this.route`.
You can define groups of routes that work with a resource:
-```javascript
-App.Router.map(function() {
+```app/router.js
+Router.map(function() {
this.resource('posts', { path: '/posts' }, function() {
this.route('new');
});
@@ -125,8 +125,8 @@ App.Router.map(function() {
As with `this.route`, you can leave off the path if it's the same as the
name of the route, so the following router is equivalent:
-```javascript
-App.Router.map(function() {
+```app/router.js
+Router.map(function() {
this.resource('posts', function() {
this.route('new');
});
@@ -148,29 +148,29 @@ This router creates three routes:
/ |
index |
- IndexController |
- IndexRoute |
+ app/controllers/index |
+ app/routes/index |
index |
N/A |
posts 1 |
- PostsController |
- PostsRoute |
+ app/controllers/posts |
+ app/routes/posts |
posts |
/posts |
posts.index |
- PostsController ↳PostsIndexController |
- PostsRoute ↳PostsIndexRoute |
+ app/controllers/posts ↳app/controllers/posts/index |
+ app/routes/posts ↳app/routes/posts/index |
posts ↳posts/index |
/posts/new |
posts.new |
- PostsController ↳PostsNewController |
- PostsRoute ↳PostsNewRoute |
+ app/controllers/posts ↳app/controllers/posts/new |
+ app/routes/posts ↳app/posts/new |
posts ↳posts/new |
@@ -181,7 +181,7 @@ This router creates three routes:
NOTE: If you define a resource using `this.resource` and **do not** supply
a function, then the implicit `resource.index` route is **not** created. In
-that case, `/resource` will only use the `ResourceRoute`, `ResourceController`,
+that case, `/resource` will only use the `route:resource`, `resource:controllers`,
and `resource` template.
Routes nested under a resource take the name of the resource plus their
@@ -217,8 +217,8 @@ into a model.
For example, if we have the resource `this.resource('posts');`, our
route handler might look like this:
-```javascript
-App.PostsRoute = Ember.Route.extend({
+```app/posts/route.js
+export default Ember.Route.extend({
model: function() {
return this.store.find('post');
}
@@ -238,13 +238,15 @@ Enter _dynamic segments_.
A dynamic segment is a portion of a URL that starts with a `:` and is
followed by an identifier.
-```javascript
-App.Router.map(function() {
+```app/router.js
+Router.map(function() {
this.resource('posts');
this.resource('post', { path: '/post/:post_id' });
});
+```
-App.PostRoute = Ember.Route.extend({
+```app/post/route.js
+export default Ember.Route.extend({
model: function(params) {
return this.store.find('post', params.post_id);
}
@@ -255,7 +257,7 @@ Because this pattern is so common, the above `model` hook is the
default behavior.
For example, if the dynamic segment is `:post_id`, Ember.js is smart
-enough to know that it should use the model `App.Post` (with the ID
+enough to know that it should use the Post model (with the ID
provided in the URL). Specifically, unless you override `model`, the route will
return `this.store.find('post', params.post_id)` automatically.
@@ -266,12 +268,14 @@ as expected out of the box.
If your model does not use the `id` property in the URL, you should
define a serialize method on your route:
-```javascript
-App.Router.map(function() {
+```app/router.js
+Router.map(function() {
this.resource('post', {path: '/posts/:post_slug'});
});
+```
-App.PostRoute = Ember.Route.extend({
+```app/post/route.js
+export default Ember.Route.extend({
model: function(params) {
// the server returns `{ slug: 'foo-post' }`
return Ember.$.getJSON('/posts/' + params.post_slug);
@@ -291,8 +295,8 @@ dynamic segment (in this case, `:post_id`).
You can nest both routes and resources:
-```javascript
-App.Router.map(function() {
+```app/router.js
+Router.map(function() {
this.resource('post', { path: '/post/:post_id' }, function() {
this.route('edit');
this.resource('comments', function() {
@@ -318,51 +322,51 @@ This router creates five routes:
/ |
index |
- App.IndexController |
- App.IndexRoute |
- index |
+ app/controllers/index |
+ app/routes/index |
+ app/templates/index |
N/A |
post |
- App.PostController |
- App.PostRoute |
- post |
+ app/controllers/post |
+ app/routes/post |
+ app/templates/post |
/post/:post_id2 |
post.index |
- App.PostIndexController |
- App.PostIndexRoute |
- post/index |
+ app/controllers/post/index |
+ app/routes/post/index |
+ app/templates/post/index |
/post/:post_id/edit |
post.edit |
- App.PostEditController |
- App.PostEditRoute |
- post/edit |
+ app/controllers/post/edit |
+ app/routes/post/edit |
+ app/templates/post/edit |
N/A |
comments |
- App.CommentsController |
- App.CommentsRoute |
- comments |
+ app/controllers/comments |
+ app/routes/comments |
+ app/templates/comments |
/post/:post_id/comments |
comments.index |
- App.CommentsIndexController |
- App.CommentsIndexRoute |
- comments/index |
+ app/controllers/comments/index |
+ app/routes/comments/index |
+ app/templates/comments/index |
/post/:post_id/comments/new |
comments.new |
- App.CommentsNewController |
- App.CommentsNewRoute |
- comments/new |
+ app/controllers/comments/new |
+ app/routes/comments/new |
+ app/templates/comments/new |
@@ -379,8 +383,8 @@ class names don't get longer the deeper nested the resources are.
You are also able to create deeply nested resources in order to preserve the namespace on your routes:
-```javascript
-App.Router.map(function() {
+```app/router.js
+Router.map(function() {
this.resource('foo', function() {
this.resource('foo.bar', { path: '/bar' }, function() {
this.route('baz'); // This will be foo.bar.baz
@@ -405,30 +409,30 @@ This router creates the following routes: