What should my Rails routes look like to work with pushState Ember.js routes?

强颜欢笑 提交于 2019-12-02 21:04:31

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.

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
David

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

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!