10

简而言之...

在构建 Ember.js 应用程序以持久保存到 Rails 应用程序时,我应该如何处理 Rails 路由/视图?我想我只需要 Rails 来呈现 application.html.erb 布局,以便 Ember.js 应用程序初始化并处理路由/视图/模板。

细节:

具体来说,如果我访问localhost:3000,在我的 Ember.js 应用程序有机会初始化之前,Rails 会在项目控制器上点击“索引”操作。它会抱怨缺少索引模板。我没有 index.html.erb 视图,因为我的 Ember.js 应用程序有一个视图/模板。

我应该为 Rails 应用程序创建空白视图吗?我的 Rails 控制器操作是否应该返回某些内容以阻止它呈现视图?或者我是否希望构建普通的 Rails 视图以与 Ember.js 应用程序视图/模板一起使用?

如果我创建一个空白项目/index.html.erb 并访问localhost:3000,Rails 将呈现它,Ember.js 将从那时起初始化并处理路由。但是,如果我直接访问localhost:3000/projects/new,Rails 会抱怨项目控制器中没有新的操作。我在 Rails 端的项目控制器上没有“新”操作,因为我不需要它。我的 Ember.js 应用程序正在处理该视图/模板。

最终,我只是不确定将 Ember.js 与 Rails 应用程序一起使用的约定是什么。

感谢您的帮助和阅读到目前为止...

编辑:

我省略了我尝试使用 Ember.js 路由器使用pushState历史记录的能力的细节。这会给我留下非散列 URL。这就是为什么我在处理 Rails 竞争路由我的应用程序时遇到问题的原因之一。

Rails 应用程序布局:

<html> 
<body>   
  <section id="design-archive"></section>
</body>
</html>

Ember.js 应用程序:

@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)

铁路路线:

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 路由:

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')

导轨控制器:

class ProjectsController < ApplicationController
  def index
    @projects = Project.all

    respond_to do |format|
      format.html
      format.json { render json: @projects }
    end
  end
end
4

4 回答 4

6

你可以有一个包罗万象的路线来引导你的 Ember 应用程序。

这是我的一个应用程序的简化示例:

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

这样做的缺点是在转到完全无效的 URL 时返回200成功而不是404错误,因为 Rails 应用程序不知道 Ember 应用程序的 URL 结构。

如果您想避免这种情况,您可以在路由中复制您的 Ember URL 结构,并将所有有效的内容指向引导路由,而不是使用包罗万象。

于 2012-08-28T11:43:26.127 回答
4

另一个更新:我已经开始使用DockYard 的教程方法来处理我的 Rails 路由,用于 pushState Ember.js 应用程序。这是一个示例 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
于 2013-04-22T13:40:00.800 回答
3

我发现这篇关于使用特定布局响应所有 HTML 请求的帖子。这是我目前正在使用的,并且似乎运行良好。唯一的限制是我不能再拥有任何非 Ember.js 驱动的普通 HTML 视图。例如,我不能在 Ember 之外使用 user_session 登录/注销表单。我想如果我到达那里,我会过那座桥。

我仍然不确定这是否是处理原始问题的最佳方法,但以下是我当前的设置。home/show.html.erb是一个空白的 Rails 视图。

控制器:

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

路线:

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
于 2012-08-29T12:27:35.260 回答
0

我建议你只有一个控制器和一个操作来呈现一个空视图,它只是初始化你的 Ember 应用程序(HomeController例如)。

然后,这是必须管理路由(所有以 开头的路由#/)的 Ember 路由器。

因此,所有其他 Rails 路由只是一个 API(由您的 Ember 应用程序使用),它返回一些 JSON。

于 2012-08-27T11:54:23.713 回答