问题
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
回答1:
You can have a catch-all route which bootstraps your Ember app.
Here's a simplified example from one of my apps:
App::Application.routes.draw do
match "/login" => "sessions#new", :via => :get, :as => :login
match "/login" => "sessions#create", :via => :post
match "/logout" => "sessions#destroy", :via => :post, :as => :logout
match "/attachments/:id" => "attachments#download"
match "/avatars/:id" => "avatars#show"
root :to => 'pages#bootstrap'
# anything not matched by the above should be served the bootstrap
match "/*path" => "pages#bootstrap"
end
This has the downside of returning 200
success instead of 404
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.
回答2:
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
:
EmberApp::Application.routes.draw do
class FormatTest
attr_accessor :mime_type
def initialize(format)
@mime_type = Mime::Type.lookup_by_extension(format)
end
def matches?(request)
request.format == mime_type
end
end
get '*foo', :to => 'ember#index', :constraints => FormatTest.new(:html)
get '/', :to => 'ember#index', :constraints => FormatTest.new(:html)
end
回答3:
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:
class ApplicationController < ActionController::Base
protect_from_forgery
before_filter :render_default_view
private
def render_default_view
return if request.xhr?
respond_to do |format|
format.html { render 'home/show' }
end
end
end
class HomeController < ApplicationController
def show
end
end
class ProjectsController < ApplicationController
def new
end
def index
end
def show
end
end
Routes:
DesignArchive::Application.routes.draw do
resources :projects, :only => [:new, :index, :show]
namespace :api do
resources :projects, :only => [:create, :index, :show, :destroy]
end
root :to => 'home#show'
end
回答4:
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.
来源:https://stackoverflow.com/questions/12116804/what-should-my-rails-routes-look-like-to-work-with-pushstate-ember-js-routes