In short...
When building an Ember.js app to persist to a Rails app, how should I handle Rails routing/views? I would think I just need Rails to render the application.html.erb layout so the Ember.js app initializes and handles the routing/view/templates.
Details:
Specifically if I visit localhost:3000, before my Ember.js app has a chance to initialize, Rails hits the "index" action on the projects controller. It will complain about a missing index template. I have no index.html.erb view as my Ember.js app has a view/template for it.
Should I be creating blank views for the Rails app? Should my Rails controller actions be returning something to prevent it from rendering a view? Or am I expected to build normal Rails views to go alongside the Ember.js app views/templates?
If I create a blank projects/index.html.erb and visit localhost:3000, Rails will render it, Ember.js will initialize and handle routing from then on. However, if I visit localhost:3000/projects/new directly Rails complains about not having a new action in the projects controller. I do not have "new" action on the projects controller on the Rails side as I don't need it. My Ember.js app is handling that view/template.
Ultimately I'm just unsure of what convention is expected to use Ember.js along side a Rails app.
Thank you for the help and reading this far...
Edit:
I left out the detail that I'm attempting to use the Ember.js Router's ability to use pushState history. This would leave me non-hashbang URL's. This is one reason why I'm having issues dealing with Rails competing to route my application.
Rails Application Layout:
<html>
<body>
<section id="design-archive"></section>
</body>
</html>
Ember.js App:
@DA = Em.Application.create
name: 'Design Archive'
VERSION: '0.1'
rootElement: '#design-archive'
ApplicationController: Em.Controller.extend()
ApplicationView: Em.View.extend
templateName: 'application'
DA.initialize(DA.Router)
Rails Routes:
DesignArchive::Application.routes.draw do
resources :clients, :only => [:new, :create, :index, :show, :destroy]
resources :projects, :only => [:new, :create, :index, :show, :destroy]
root :to => 'projects#index'
end
Ember.js Routes:
DA.Router = Em.Router.create
location: 'history'
root: Em.Route.extend
index: Em.Route.extend
route: '/'
redirectsTo: 'projects'
# Actions
doProjects: (router) ->
router.transitionTo('projects')
doProjectsNew: (router) ->
router.transitionTo('newProject')
# Routes
projects: Em.Route.extend
route: '/projects'
index: Em.Route.extend
router: '/'
connectOutlets: (router) ->
router.get('applicationController').connectOutlet('projects', DA.Project.find())
showProject: Em.Route.transitionTo('project')
project: Em.Route.extend
route: '/projects/:project_id'
connectOutlets: (router, project) ->
router.get('applicationController').connectOutlet('project', project)
projectsIndex: Em.Route.transitionTo('projects')
newProject: Em.Route.extend
route: '/projects/new'
connectOutlets: (router) ->
router.get('applicationController').connectOutlet('projectsNew')
Rails Controller:
class ProjectsController < ApplicationController
def index
@projects = Project.all
respond_to do |format|
format.html
format.json { render json: @projects }
end
end
end
You can have a catch-all route which bootstraps your Ember app.
Here's a simplified example from one of my apps:
This has the downside of returning
200
success instead of404
errors when going to completely invalid URLs, as the Rails app doesn't know anything about the URL structure of the Ember app.If you wanted to avoid that you could replicate your Ember URL structure in the routes and just point everything valid through to the bootstrap route instead of using the catch-all.
Another update: I've since started using DockYard's tutorial method for handling my Rails routes for a pushState Ember.js application. Here's an example Rails
routes.rb
:I found this post on responding to all HTML request with a specific layout. It is what I'm currently using and seems to work well. The only limitation would be that I could no longer have any non-Ember.js driven normal HTML views. For instance, I could not have user_session login/logout forms outside of Ember. I suppose I'll cross that bridge when if I get there.
I'm still not sure if this is the best way to handle my original problem, but below is my current setup. home/show.html.erb is a blank Rails view.
Controllers:
Routes:
I suggest you to have only one controller with one action for rendering an empty view, which just initialize your Ember application (an
HomeController
for example).Then, this is the Ember router that must manage routes (all routes starting with
#/
).Consequently, all other Rails routes are just an API (used by your Ember app), which return some JSON.