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

Короче ...

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

Подробности:

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

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

Если я создам пустой файл projects / index.html.erb и перейду на localhost: 3000, Rails отобразит его, Ember.js будет инициализировать и обрабатывать маршрутизацию с этого момента. Однако, если я захожу непосредственно на localhost: 3000 / projects / new, Rails жалуется на отсутствие нового действия в контроллере проектов. У меня нет "нового" действия в контроллере projects на стороне 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)

Маршруты 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

person David    schedule 24.08.2012    source источник


Ответы (4)


У вас может быть комплексный маршрут, который загружает ваше приложение 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 успеха вместо 404 ошибок при переходе к полностью недопустимым URL-адресам, поскольку приложение Rails ничего не знает о структуре URL-адресов приложения Ember.

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

person rlivsey    schedule 28.08.2012
comment
Спасибо за предложение @rlivsey. - person David; 29.08.2012

Еще одно обновление: с тех пор я начал использовать учебный метод 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
person David    schedule 22.04.2013
comment
Я делаю :constraints => { :format => 'html' } вместо определения настраиваемого объекта ограничения. См. guides.rubyonrails.org/routing.html#request-based-constraints - person Mukund Lakshman; 13.04.2014

Я нашел этот пост при ответе на все запросы 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
person David    schedule 29.08.2012

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

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

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

person louiscoquio    schedule 27.08.2012
comment
Спасибо за совет @louiscoquio. Я упустил один бит информации, и это то, что я пытаюсь использовать способность маршрутизатора Ember.js использовать историю pushState. Полагаю, это может быть причиной того, что у меня возникают проблемы с попытками Rails маршрутизировать мое приложение. Я обновлю свой пост. docs.emberjs.com/#doc=Ember.HistoryLocation&src=false - person David; 27.08.2012