README.md
# ember-rails [![Build Status](https://secure.travis-ci.org/emberjs/ember-rails.svg?branch=master)](http://travis-ci.org/emberjs/ember-rails) [![Dependency Status](https://gemnasium.com/emberjs/ember-rails.svg)](https://gemnasium.com/emberjs/ember-rails) [![Code Climate](https://codeclimate.com/github/emberjs/ember-rails/badges/gpa.svg)](https://codeclimate.com/github/emberjs/ember-rails)
ember-rails makes developing an [Ember.JS](http://emberjs.com/) application much easier in Rails 4.2+.
The following functionalities are included in this gem:
- Pre-compiling of your handlebars templates when building your asset pipeline.
- Inclusion of development and production copies of Ember, [Ember Data](https://github.com/emberjs/data) and [Handlebars](https://github.com/wycats/handlebars.js).
- Inclusion of [ActiveModel::Serializer](https://github.com/rails-api/active_model_serializers) for integration with Ember Data.
You can see an example of how to use the gem [here](https://github.com/keithpitt/ember-rails-example). There is also a great tutorial by [Dan Gebhardt](https://twitter.com/#!/dgeb) called "[Beginning Ember.js on Rails](http://www.cerebris.com/blog/2012/01/24/beginning-ember-js-on-rails-part-1/)" which is a great read if you're just starting out with Rails and Ember.js.
## Getting started
* Add the gem to your application Gemfile:
```ruby
gem 'ember-rails'
# gem 'ember-source' # You can specify the Ember.js version you want to use.(such as '~> 1.13.0')
```
* Run `bundle install`
* Next, generate the application structure:
```shell
$ rails generate ember:bootstrap
```
* Restart your server (if it's running)
## Building a new project from scratch
Rails supports the ability to build projects from a template source ruby file.
To build an Ember centric Rails project you can simply type the following into your command line:
```shell
$ rails new my-app -m https://emberjs.com/edge_template.rb
```
Read more about [Rails application templates](http://edgeguides.rubyonrails.org/rails_application_templates.html) and take a look at the edge_template.rb [source code](https://github.com/emberjs/website/blob/master/source/edge_template.rb).
Notes:
To install the latest builds of ember and ember-data. It should be noted that the
examples in the [getting started guide](http://emberjs.com/guides/getting-started/)
have been designed to use the released version of ember:
```shell
$ rails generate ember:install
```
You'll probably need to clear out your cache after doing this with:
```shell
$ rake tmp:clear
```
Also, ember-rails includes some flags for the bootstrap generator:
```
--ember-path or -d # custom ember path
--skip-git or -g # skip git keeps
--javascript-engine # engine for javascript (js, coffee, em or es6)
--app-name or -n # custom ember app name
```
## For CoffeeScript support
Add coffee-rails to the Gemfile
```ruby
gem 'coffee-rails'
```
Run the bootstrap generator in step 4 with an extra flag instead:
```shell
$ rails g ember:bootstrap -g --javascript-engine coffee
```
## For EmberScript support
[EmberScript](http://www.emberscript.com) is a dialect of CoffeeScript
with extra support for computed properties (which do not have to be
explicitly declared), the `class` / `extends` syntax, and extra syntax
to support observers and mixins.
To get EmberScript support, make sure you have the following in your
Gemfile:
```ruby
gem 'ember_script-rails', :github => 'ghempton/ember-script-rails'
```
You can now use the flag `--javascript-engine=em` to specify EmberScript
assets in your generators, but all of the generators will default to
using an EmberScript variant first.
## For ES6 support
Ember.js recommends using ES6 syntax.
It is supported by [Babel](https://babeljs.io/) via [ember-es6_template](https://github.com/tricknotes/ember-es6_template).
Run the bootstrap generator with an extra flag:
```shell
$ rails g ember:bootstrap --javascript-engine=es6
```
Note:
To use ES6 module in your application, the following configuration is required:
### Single Ember Application
This is the case for single Ember application in `app/assets/javascripts` (not under the subdirectory).
`my-app.es6`
``` javascript
import Application from 'ember-rails/application';
const App = Application.extend({
// Configure your application.
});
App.create();
```
`import Application from 'ember-rails/application';` and `Application.extend()` is important.
It provides customized Ember application to resolve dependencies from ES6 modules instead of `Ember.Application.extend()`.
`application.js`
``` javascript
//= require jquery
//= require ember
//= require ember-data
//= require ember-rails/application
//= require ./my-app
//= require_self
require('my-app'); // Run your Ember.js application
```
### Multiple Ember Application
This is the case for multiple Ember application in your Rails application.
(Or your Ember application is placed in sub directories of `app/assets/javascripts`.)
First, you should configure `config.ember.module_prefix` to `nil`.
To disable prepending the module prefix to you modules.
`config/application.rb`
``` ruby
config.ember.module_prefix = nil
```
Second, please specify `modulePrefix` to your Ember application.
`my-app/application.module.es6`
``` javascript
import Application from 'ember-rails/application';
import loadInitializers from 'ember/load-initializers';
const App = Application.extend({
modulePrefix: 'my-app' // This value should be the same as directory name.
});
loadInitializers(App, 'my-app');
App.create();
```
Last, add your endpoint to where you want to run your Ember application.
``` javascript
require('my-app'); // Run your Ember.js application
```
## Configuration Options
The following options are available for configuration in your application or environment-level
config files (`config/application.rb`, `config/environments/development.rb`, etc.):
| Configuration Option | Description |
|----------------------------------------------|---------------------------------------------------------------------------------------------------------------------|
| `config.ember.variant` | Determines which Ember variant to use. Valid options: `:development`, `:production`. Defaults to `:production` in production, and `:development` everywhere else. |
| `config.ember.app_name` | Specificies a default application name for all generators. |
| `config.ember.ember_path` | Specifies a default custom root path for all generators. |
| `config.ember.module_prefix` | Sets module prefix for es6 module. This option is used for only `es6` scripts. Default value: `ember-app`. |
| `config.ember.prefix_files` | Sets some file names to add `config.ember.module_prefix` into its file name as es6 module name. |
| `config.ember.prefix_dirs` | Sets some dir names to add `config.ember.module_prefix` into its directory name as es6 module name. |
| `config.handlebars.precompile` | Enables or disables precompilation. Default value: `true`. |
| `config.handlebars.templates_root` | Sets the root path (under `app/assets/javascripts`) for templates to be looked up in. Default value: `"templates"`. |
| `config.handlebars.templates_path_separator` | The path separator to use for templates. Default value: `'/'`. |
| `config.handlebars.output_type` | Configures the style of output (options are `:amd` and `:global`). Default value: `:global`. |
| `config.handlebars.amd_namespace` | Configures the module prefix for AMD formatted output. Default value: `nil`. |
| `config.handlebars.ember_template` | Default which Ember template type to compile. Valid options: `'Handlebars', `HTMLBars`. Defaults to 'Handlebars`' when `Ember::VERSION` is under 1.10.0, `HTMLBars` when `Ember::VERSION` is over 1.10.0. |
Note:
In a mountable engine, ember-rails will not recognize any configurations.
Instead, use command line options.
## Enabling Features with Feature Flags
See [the guide](http://emberjs.com/guides/configuring-ember/feature-flags/#toc_flagging-details) and check [features.json](https://github.com/emberjs/ember.js/blob/master/features.json) for the version of Ember you're using.
If a feature is set to false, you will need to compile ember from source yourself to include it.
### Important note for projects that render JSON responses
ember-rails includes [active_model_serializers](https://github.com/rails-api/active_model_serializers) which affects how ActiveModel and ActiveRecord objects get serialized to JSON, such as when using `render json:` or `respond_with`. By default active_model_serializers adds root elements to these responses (such as adding `{"posts": [...]}` for `render json: @posts`) which will affect the structure of your JSON responses.
To disable this effect on your JSON responses, put this in an initializer:
```Ruby
# Stop active_model_serializers from adding root elements to JSON responses.
ActiveModel::Serializer.root = false
ActiveModel::ArraySerializer.root = false
```
See the [active_model_serializers](https://github.com/rails-api/active_model_serializers) documentation for a more complete understanding of other effects this dependency might have on your app.
## Architecture
Ember does not require an organized file structure. However, ember-rails allows you
to use `rails g ember:bootstrap` to create the following directory structure under `app/assets/javascripts`:
```
├── adapters
├── components
├── controllers
├── helpers
├── mixins
├── models
├── practicality.coffee
├── router.coffee
├── routes
├── templates
│ └── components
└── views
```
Additionally, it will add the following lines to `app/assets/javascripts/application.js`.
By default, it uses the Rails Application's name and creates an `rails_app_name.js`
file to set up application namespace and initial requires:
```javascript
//= require ember
//= require ember-data
//= require_self
//= require rails_app_name
RailsAppName = Ember.Application.create();
```
*Example:*
```shell
$ rails g ember:bootstrap
insert app/assets/javascripts/application.js
create app/assets/javascripts/models
create app/assets/javascripts/models/.gitkeep
create app/assets/javascripts/controllers
create app/assets/javascripts/controllers/.gitkeep
create app/assets/javascripts/views
create app/assets/javascripts/views/.gitkeep
create app/assets/javascripts/helpers
create app/assets/javascripts/helpers/.gitkeep
create app/assets/javascripts/components
create app/assets/javascripts/components/.gitkeep
create app/assets/javascripts/templates
create app/assets/javascripts/templates/.gitkeep
create app/assets/javascripts/templates/components
create app/assets/javascripts/templates/components/.gitkeep
create app/assets/javascripts/mixins
create app/assets/javascripts/mixins/.gitkeep
create app/assets/javascripts/adapters
create app/assets/javascripts/adapters/.gitkeep
create app/assets/javascripts/app.js
```
If you want to avoid `.gitkeep` files, use the `skip git` option like
this: `rails g ember:bootstrap -g`.
Ask Rails to serve HandlebarsJS and pre-compile templates to Ember
by putting each template in a dedicated ".hbs", ".js.hjs" or ".handlebars" file
(e.g. `app/assets/javascripts/templates/admin_panel.hbs`)
and including the assets in your layout:
```erb
<%= javascript_include_tag "templates/admin_panel" %>
```
If you want to avoid the `templates` prefix, set the `templates_root` option in your application configuration block:
```ruby
config.handlebars.templates_root = 'ember_templates'
```
If you store templates in a file like `app/assets/javascripts/ember_templates/admin_panel.hbs` after setting the above config,
it will be made available to Ember as the `admin_panel` template.
_(Note: you must clear the local sprockets cache after modifying `templates_root`, stored by default in `tmp/cache/assets`)_
Default behavior for ember-rails is to precompile handlebars templates.
If you don't want this behavior you can turn it off in your application configuration (or per environment in: `config/environments/development.rb`) block:
```ruby
config.handlebars.precompile = false
```
_(Note: you must clear the local sprockets cache if you disable precompilation, stored by default in `tmp/cache/assets`)_
Bundle all templates together thanks to Sprockets,
e.g create `app/assets/javascripts/templates/all.js` with:
```js
//= require_tree .
```
Now a single line in the layout loads everything:
```erb
<%= javascript_include_tag "templates/all" %>
```
### Note about ember components
When necessary, ember-rails adheres to a conventional folder structure. To create an ember component you must define the handlebars file *inside* the *components* folder under the templates folder of your project to properly register your handlebars component file.
*Example*
Given the following folder structure:
```
├── adapters
├── components
├── controllers
├── helpers
├── mixins
├── models
├── practicality.coffee
├── router.coffee
├── routes
├── templates
│ └── components
│ └── my-component.hbs
└── views
```
and a `my-component.hbs` file with the following contents:
```hbs
<h1>My Component</h1>
```
It will produce the following handlebars output:
```html
<script type="text/x-handlebars" id="components/my-component">
<h1>My Component</h1>
</script>
```
You can reference your component inside your other handlebars template files by the handlebars file name:
```hbs
{{ my-component }}
```
## Specifying Different Versions of Ember/Handlebars/Ember-Data
By default, ember-rails ships with the latest version of
[Ember](https://rubygems.org/gems/ember-source/versions),
[Handlebars](https://rubygems.org/gems/handlebars-source/versions),
and [Ember-Data](https://rubygems.org/gems/ember-data-source/versions).
To specify a different version that'll be used for both template
precompilation and serving to the browser, you can specify the desired
version of one of the above-linked gems in the Gemfile, e.g.:
```ruby
gem 'ember-source', '~> 1.13.0'
```
You can also specify versions of 'handlebars-source' and
'ember-data-source', but note that an appropriate 'handlebars-source'
will be automatically chosen depending on the version of 'ember-source'
that's specified.
You can also override the specific ember.js, handlebars.js, and
ember-data.js files that'll be `require`d by the Asset pipeline by
placing these files in `vendor/assets/ember/development` and
`vendor/assets/ember/production`, depending on the `config.ember.variant`
you've specified in your app's configuration, e.g.:
```ruby
config.ember.variant = :production
# config.ember.variant = :development
```
## Updating Ember
If at any point you need to update Ember.js from any of the release channels, you can do that with
```shell
$ rails generate ember:install --channel=<channel>
```
This will fetch both Ember.js and Ember Data from [http://builds.emberjs.com/](http://builds.emberjs.com/) and copy to the right directory. You can choose between the following channels:
* canary - This references the 'master' branch and is not recommended for production use.
* beta - This references the 'beta' branch, and will ultimately become the next stable version. It is not recommended for production use.
* release - This references the 'stable' branch, and is recommended for production use.
When you don't specify a channel, the release channel is used.
It is also possible to download a specific tagged release. To do this, use the following syntax:
```shell
$ rails generate ember:install --tag=v1.13.0 --ember
```
or for ember-data
```shell
$ rails generate ember:install --tag=v1.13.0 --ember-data
```
## CSRF Token
Rails [`protect_from_forgery`](http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection/ClassMethods.html#method-i-protect_from_forgery) requires CSRF token for every XHR except GET.
The CSRF token is normally found in `app/views/layouts/application.html.*` inserted with the rails helper: [`csrf_meta_tags`](http://api.rubyonrails.org/classes/ActionView/Helpers/CsrfHelper.html#method-i-csrf_meta_tags).
When you use [jquery-ujs](https://github.com/rails/jquery-ujs),
the CSRF token will be sent to the rails application on every XHR automatically.
If not so, the following JavaScript is required in your code.
``` javascript
$.ajaxPrefilter(function(options, originalOptions, xhr) {
var token = $('meta[name="csrf-token"]').attr('content');
xhr.setRequestHeader('X-CSRF-Token', token);
});
```
## Note on Patches/Pull Requests
1. Fork the project.
2. Make your feature addition or bug fix.
3. Add tests for it. This is important so I don't break it in a future version unintentionally.
4. Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
5. Send me a pull request. Bonus points for topic branches.