# Ember CLI Rails Unify your EmberCLI and Rails Workflows! EmberCLI-Rails is designed to give you the best of both worlds: * Stay up to date with the latest JavaScript technology and EmberCLI addons * Develop your Rails API and Ember front-ends from within a single process * Inject Rails-generated content into your EmberCLI application * Avoid Cross-Origin Resource Sharing gotchas by serving your EmberCLI applications and your API from a single domain * Write truly end-to-end integration tests, exercising your application's entire stack through JavaScript-enabled Capybara tests * Deploy your entire suite of applications to Heroku with a single `git push` If you're having trouble, checkout the [example project]! **EmberCLI-Rails Supports EmberCLI 1.13.13 and later.** [example project]: https://github.com/seanpdoyle/ember-cli-rails-heroku-example ## Install Add the following to your `Gemfile`: ```ruby gem "ember-cli-rails" ``` Then run `bundle install`: ```bash $ bundle install ``` If you haven't created an Ember application yet, generate a new one: ```bash $ ember new frontend --skip-git ``` ## Setup First, generate the gem's initializer: ```bash $ rails generate ember:init ``` This will create the following initializer: ```ruby # config/initializers/ember.rb EmberCli.configure do |c| c.app :frontend end ``` This initializer assumes that your Ember application exists in `Rails.root.join("frontend")`. If this is not the case, you could * move your existing Ember application into `Rails.root.join("frontend")` * configure `frontend` to reference the Ember application in its current directory: ```rb c.app :frontend, path: "~/projects/my-ember-app" ``` **Initializer options** - `name` - this represents the name of the Ember CLI application. - `path` - the path where your Ember CLI application is located. The default value is the name of your app in the Rails root. ```ruby EmberCli.configure do |c| c.app :adminpanel # path defaults to `Rails.root.join("adminpanel")` c.app :frontend, path: "/path/to/your/ember-cli-app/on/disk" end ``` Next, install the [ember-cli-rails-addon][addon]: ```bash $ cd path/to/frontend $ ember install ember-cli-rails-addon ``` Be sure that the addon's [`MAJOR` and `MINOR` version][semver] matches the gem's `MAJOR` and `MINOR` versions. For instance, if you're using the `0.6.x` version of the gem, specify `~> 0.6.0` in your Ember app's `package.json`: ```json { "devDependencies": { "ember-cli-rails-addon": "~> 0.6.0" } } ``` [addon]: https://github.com/rondale-sc/ember-cli-rails-addon/ [semver]: http://semver.org/ ## Mount Configure Rails to route requests to the `frontend` Ember application: ```rb # config/routes.rb Rails.application.routes.draw do mount_ember_app :frontend, to: "/" end ``` **Routing options** * `to` - The path to handle as an Ember application. This will only apply to `format: :html` requests. Additionally, this will handle child routes as well. For instance, mounting `mount_ember_app :frontend, to: "/frontend"` will handle a `format: :html` request to `/frontend/posts`. * `controller` - Defaults to `"ember_cli/ember"` * `action` - Defaults to `"index"` Finally, install your Ember application's dependencies: ```bash $ rake ember:install ``` Boot your Rails application, navigate to `"/"`, and view your EmberCLI application! ## Develop EmberCLI Rails exposes several useful rake tasks. **`ember:install`** Install the Ember applications' dependencies. **`ember:compile`** Compile the Ember applications. **`ember:test`** Execute Ember's test suite. If you're using Rake to run the test suite, make sure to configure your test task to depend on `ember:test`. For example, to configure a bare `rake` command to run both RSpec and Ember test suites, configure the `default` task to depend on both `spec` and `ember:test`. ```rb task default: [:spec, "ember:test"] ``` ## Deploy In production environments, assets should be served over a Content Delivery Network. Configuring an `ember-cli-rails` application to serve Ember's assets over a CDN is very similar to [configuring an EmberCLI application to serve assets over a CDN][ember-cli-cdn]: [ember-cli-cdn]: http://ember-cli.com/user-guide/#fingerprinting-and-cdn-urls ```js var app = new EmberApp({ fingerprint: { prepend: 'https://cdn.example.com/' } }); ``` If you're serving the Ember application from a path other than `"/"`, the `prepend` URL must end with the mounted path: ```js var app = new EmberApp({ fingerprint: { // for an Ember application mounted to `/admin_panel/` prepend: 'https://cdn.example.com/admin_panel/', } }); ``` As long as your [CDN is configured to pull from your Rails application][dns-cdn] , your assets will be served over the CDN. [dns-cdn]: https://robots.thoughtbot.com/dns-cdn-origin ### Deployment Strategies By default, EmberCLI-Rails will serve the `index.html` file that `ember build` produces. If you need to override this behavior (for instance, if you're using [`ember-cli-deploy`'s "Lightning Fast Deployment"][lightning] strategy in `production`), you can specify the strategy's class in the initializer: ```rb EmberCli.configure do |config| config.app :frontend, deploy: { production: EmberCli::Deploy::Redis } end ``` This example configures the `frontend` Ember application to retrieve the index's HTML from an [`ember-cli-deploy-redis`][ember-cli-deploy-redis] -populated Redis entry using the [`ember-cli-rails-deploy-redis`][ember-cli-rails-deploy-redis] gem. If you're deploying HTML with a custom strategy in `development` or `test`, disable EmberCLI-Rails' build step by setting `ENV["SKIP_EMBER"] = true`. **NOTE:** Specifying a deployment strategy is only supported for applications that use the `mount_ember_app` and `render_ember_app` helpers. [ember-cli-deploy-redis]: https://github.com/ember-cli-deploy/ember-cli-deploy-redis [ember-cli-rails-deploy-redis]: https://github.com/seanpdoyle/ember-cli-rails-deploy-redis [lightning]: https://github.com/ember-cli-deploy/ember-cli-deploy-lightning-pack ### Heroku To configure your EmberCLI-Rails applications for Heroku: 1. Execute `rails generate ember:heroku` 1. [Add the NodeJS buildpack][buildpack] and configure NPM to include the `bower` dependency's executable file. ```sh $ heroku buildpacks:clear $ heroku buildpacks:add --index 1 https://github.com/heroku/heroku-buildpack-nodejs $ heroku buildpacks:add --index 2 https://github.com/heroku/heroku-buildpack-ruby $ heroku config:set NPM_CONFIG_PRODUCTION=false $ heroku config:unset SKIP_EMBER ``` You are ready to deploy: ```bash $ git push heroku master ``` **NOTE** Run the generator each time you introduce additional EmberCLI applications into the project. [buildpack]: https://devcenter.heroku.com/articles/using-multiple-buildpacks-for-an-app#adding-a-buildpack ### Capistrano EmberCLI-Rails executes both `npm install` and `bower install` during EmberCLI's compilation, triggered by the `asset:precompilation` rake task. The `npm` and `bower` executables are required to be defined in the deployment SSH session's `$PATH`. It is not sufficient to modify the session's `$PATH` in a `.bash_profile`. To resolve this issue, prepend the Node installation's `bin` directory to the target system's `$PATH`: ```ruby #config/deploy/production.rb set :default_env, { "PATH" => "/home/deploy/.nvm/versions/node/v4.2.1/bin:$PATH" } ``` The system in this example is using `nvm` to configure the node version. If you're not using `nvm`, make sure the string you prepend to the `$PATH` variable contains the directory or directories that contain the `bower` and `npm` executables. ## Override By default, routes defined by `ember_app` will be rendered with the internal `EmberCli::EmberController`. ### Overriding the view The `EmberCli::EmberController` renders the Ember application's `index.html` and injects the Rails-generated CSRF tags into the `
`. To customize the view, create `app/views/ember_cli/ember/index.html.erb`: ```erb <%= render_ember_app ember_app do |head| %> <% head.append do %> <%= csrf_meta_tags %> <% end %> <% end %> ``` The `ember_app` helper is available within the `EmberCli::EmberController`'s view, and refers to the name of the current EmberCLI application. To inject the EmberCLI generated `index.html`, use the `render_ember_app` helper in your view: ```erb <%= render_ember_app :frontend do |head, body| %> <% head.append do %> <%= csrf_meta_tags %> <% end %> <% body.append do %> <%= render partial: "my-analytics" %> <% end %> <% end %> ``` The `body` block argument and the corresponding call to `body.append` in the example are both optional, and can be omitted. ### Overriding the controller To override this behavior, you can specify [any of Rails' routing options] [route-options]. [route-options]: http://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/Base.html#method-i-match For the sake of this example, override the `controller` and `action` options: ```rb # config/routes Rails.application.routes.draw do mount_ember_app :frontend, to: "/", controller: "application", action: "index" end ``` When serving the EmberCLI generated `index.html` with the `render_ember_app` helper, make sure the controller's `layout` is disabled, as EmberCLI generates a fully-formed HTML document: ```rb # app/controllers/application.rb class ApplicationController < ActionController::Base def index render layout: false end end ``` ### Rendering the EmberCLI generated JS and CSS Rendering EmberCLI applications with `render_ember_app` is the recommended, actively supported method of serving EmberCLI applications. However, for the sake of backwards compatibility, `ember-cli-rails` supports injecting the EmberCLI-generated assets into an existing Rails layout. Following the example above, configure the mounted EmberCLI application to be served by a custom controller (`ApplicationController`, in this case). In the corresponding view, use the asset helpers: ```erb <%= include_ember_script_tags :frontend %> <%= include_ember_stylesheet_tags :frontend %> ``` ### Mounting multiple Ember applications Rendering Ember applications to paths other than `/` requires additional configuration. Consider a scenario where you had Ember applications named `frontend` and `admin_panel`, served from `/` and `/admin_panel` respectively. First, specify the Ember applications in the initializer: ```ruby EmberCli.configure do |c| c.app :frontend c.app :admin_panel, path: "path/to/admin_ember_app" end ``` Next, mount the applications alongside the rest of Rails' routes: ```rb # /config/routes.rb Rails.application.routes.draw do mount_ember_app :frontend, to: "/" mount_ember_app :admin_panel, to: "/admin_panel" end ``` Then set each Ember application's `baseURL` to the mount point: ```javascript // frontend/config/environment.js module.exports = function(environment) { var ENV = { modulePrefix: 'frontend', environment: environment, baseURL: '/', // ... } }; // path/to/admin_ember_app/config/environment.js module.exports = function(environment) { var ENV = { modulePrefix: 'admin_panel', environment: environment, baseURL: '/admin_panel', // originally '/' // ... } }; ``` Finally, configure EmberCLI's fingerprinting to prepend the mount point to the application's assets: ```js // frontend/ember-cli-build.js module.exports = function(defaults) { var app = new EmberApp(defaults, { fingerprint: { // matches the `/` mount point prepend: 'https://cdn.example.com/', } }); }; // path/to/admin_ember_app/ember-cli-build.js module.exports = function(defaults) { var app = new EmberApp(defaults, { fingerprint: { // matches the `/admin_panel` mount point prepend: 'https://cdn.example.com/admin_panel/', } }); }; ``` When injecting the EmberCLI-generated assets with the `include_ember_script_tags` and `include_ember_stylesheet_tags` helpers to a path other than `"/"`, a `