Как должны выглядеть маршруты Rails для работы с маршрутами pushState Ember.js?

Короче...

При создании приложения Ember.js для сохранения приложения Rails, как мне обрабатывать маршрутизацию/представления Rails? Я бы подумал, что мне просто нужны Rails для рендеринга layout.html.erb, поэтому приложение Ember.js инициализирует и обрабатывает маршрутизацию/просмотр/шаблоны.

Детали:

В частности, если я посещаю localhost: 3000, перед тем как мое приложение Ember.js имеет возможность инициализировать, Rails обращается к действию "index" на контроллере проектов. Он будет жаловаться на отсутствующий шаблон индекса. У меня нет index.html.erb view, так как у моего приложения Ember.js есть шаблон/шаблон для него.

Должен ли я создавать пустые представления для приложения Rails? Должны ли мои действия контроллера Rails возвращать что-то, чтобы предотвратить его отображение? Или я ожидаю, что вы создадите обычные представления Rails, чтобы идти вместе с представлениями/шаблонами приложения Ember.js?

Если я создаю пустые проекты /index.html.erb и посещу localhost: 3000, Rails отобразит его, Ember.js инициализирует и обрабатывает маршрутизацию с этого момента. Однако, если я посещаю localhost: 3000/projects/new, Rails жалуется на отсутствие нового действия в контроллере проектов. У меня нет "нового" действия над контроллером проектов на стороне Rails, поскольку он мне не нужен. Приложение My Ember.js обрабатывает этот вид/шаблон.

В конечном счете, я просто не знаю, какое соглашение, как ожидается, будет использовать Ember.js вместе с Rails-приложением.

Благодарим вас за помощь и прочтение этого...

Edit:

Я забыл детали, что я пытаюсь использовать способность Ember.js Router использовать историю pushState. Это оставило бы меня не-hashbang 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)

Маршруты Rails:

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

Контроллер Rails:

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

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

Ответ 1

Другое обновление: с тех пор я начал использовать метод DockYard tutorial для обработки маршрутов 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

Ответ 2

У вас может быть весь маршрут, который загружает ваше приложение 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

Это приводит к отрицательному результату вместо 200 при возврате 200 ошибок при переходе на полностью недействительные URL-адреса, поскольку приложение Rails ничего не знает о структуре URL-адреса приложения Ember.

Если вы хотите избежать того, что вы могли бы реплицировать свою структуру URL-адресов Ember на маршрутах и ​​просто указывать все действия до исходного маршрута, вместо использования catch-all.

Ответ 3

Я нашел этот пост для ответа на весь запрос HTML с определенным макетом. Это то, что я сейчас использую и, кажется, хорошо работает. Единственным ограничением было бы то, что я больше не мог иметь никаких обычных HTML-представлений, отличных от Ember.js. Например, я не мог иметь регистрационные/пользовательские формы user_session вне Ember. Полагаю, я перейду через этот мост, когда я приеду туда.

Я все еще не уверен, что это лучший способ справиться с моей оригинальной проблемой, но ниже моя текущая настройка. 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

Ответ 4

Я предлагаю вам иметь только один контроллер с одним действием для рендеринга пустого представления, которое просто инициализирует ваше приложение Ember (например, HomeController).

Затем это маршрутизатор Ember, который должен управлять маршрутами (все маршруты начинаются с #/).

Следовательно, все остальные маршруты Rails - это просто API (используемый вашим приложением Ember), которые возвращают некоторый JSON.