Go to English Blog

Configurando o Ember.js no Rails

Leia em 5 minutos

Ember.js

Ember.js é um framework client-side que permite criar single-page applications. Ele fornece uma série de ferramentas que abstraem os patterns mais comuns. Seguindo o conceito de Convenção sobre Configuração, o Ember consegue diminuir a necessidade de se criar boilerplates para coisas comuns, liberando o desenvolvedor para focar no que realmente importa.

A ferramenta mais usada no momento para executar projetos Ember é o ember-cli. Escrita em Node.js, ela permite gerar e executar aplicações Ember e possui funcionalidades como asset pipeline e transpiler para ES6 (a nova versão do JavaScript). Mesmo com todo este poder, existem situações onde você pode querer não sair do Rails. Afinal, usar uma outra ferramenta com certeza aumentará a complexidade do workflow e, por que não, do projeto como um todo.

Neste artigo veremos como configurar o Ember em uma aplicação Ruby on Rails, com suporte a testes usando QUnit.

Atenção: Este artigo possui uma nova versão que usa ember-cli. Leia a artigo mais recente.

Instalação

Para instalar o Ember em uma aplicação, basta adicionar algumas gems ao seu arquivo Gemfile. Para executar o Ember você precisa do jQuery; para instalar sua versão mais recente iremos usar o Rails Assets, um proxy entre o Rubygems/Bundler e o Bower.

Veja como fica o Gemfile inicial para uma aplicação com Rails 4.2 e Ember 1.9.

source 'https://rubygems.org'
source 'https://rails-assets.org'

gem 'rails', '4.2.0'
gem 'sass-rails', '~> 5.0'
gem 'uglifier', '>= 1.3.0'
gem 'ember-rails'
gem 'ember-source', '~> 1.9.0'
gem 'rails-assets-jquery'

Instale as dependências com o comando bundle install.

Configurando nosso projeto

Agora chegou a hora de gerar o projeto Ember. Para isso, basta executar o comando rails generate. Você pode aproveitar para especificar o namespace de sua aplicação com o switch -n.

$ rails g ember:bootstrap -n MyApp
    insert  app/assets/javascripts/application.js
    create  app/assets/javascripts/models
    create  app/assets/javascripts/models/.gitkeep
    create  app/assets/javascripts/controllers
    create  app/assets/javascripts/controllers/.gitkeep
    create  app/assets/javascripts/views
    create  app/assets/javascripts/views/.gitkeep
    create  app/assets/javascripts/routes
    create  app/assets/javascripts/routes/.gitkeep
    create  app/assets/javascripts/helpers
    create  app/assets/javascripts/helpers/.gitkeep
    create  app/assets/javascripts/components
    create  app/assets/javascripts/components/.gitkeep
    create  app/assets/javascripts/templates
    create  app/assets/javascripts/templates/.gitkeep
    create  app/assets/javascripts/templates/components
    create  app/assets/javascripts/templates/components/.gitkeep
    create  app/assets/javascripts/mixins
    create  app/assets/javascripts/mixins/.gitkeep
    create  app/assets/javascripts/adapters
    create  app/assets/javascripts/adapters/.gitkeep
    create  app/assets/javascripts/codeplane.js
    create  app/assets/javascripts/router.js
    create  app/assets/javascripts/store.js
    create  app/assets/javascripts/adapters/application_adapter.js

Abra o arquivo app/assets/javascripts/application.js e modifique-o para remover coisas como jquery-ujs e turbolinks.

//= require jquery
//= require handlebars
//= require ember
//= require ember-data
//= require_self
//= require ./my_app

MyApp = Ember.Application.create();

Você também vai precisar criar o controller que fará o bootstrap da aplicação. Você criar o controller/action EmberController#bootstrap. Ela não precisa fazer nada, apenas existir.

class EmberController < ApplicationController
  def bootstrap
  end
end

Embora definir o método da action não seja necessário, gosto de fazer isso para dar visibilidade. Lembre-se de criar o arquivo de template app/views/ember/bootstrap.html.erb; ele pode ficar em branco.

Agora chegou a hora de criar nossas rotas. O Ember tem suporte para history.pushState; isso significa que toda vez que você visitar uma nota rota, a URL do navegador será alterada, em vez de usar #!. Para que todas as rotas sejam mapeadas para a action EmberController#bootstrap, precisamos criar uma rota catch-all. Seu arquivo config/routes.rb será algo assim:

Rails.application.routes.draw do
  root 'ember#bootstrap'
  get '/*path' => 'ember#bootstrap'
end

Crie o arquivo app/javascripts/templates/index.hbs com o conteúdo abaixo. Assim poderemos ver se tudo funcionou como deveria.

<h1>Welcome to Ember.js</h1>
<p>Fuck yeah! It works!</p>

Finalmente inicie o servidor com o comando rails server e acesse o endereço http://localhost:3000. Se tudo deu certo, você deverá ver a página que criou anteriormente.

Ember.js rodando no Ruby on Rails

Configurando o ambiente de testes

O Ember.js é integrado com o QUnit. Por isso, não invente: use-o. Caso contrário, todos os helpers disponíveis não poderão ser usados. Além disso, existe muito mais documentação disponível para Ember com QUnit do que com os outros frameworks.

Configurar o Rails para rodar testes do Ember era uma tarefa complicada. Por isso decidi escrever um test runner específico para Rails, Ember e QUnit. Adicione a gem test_squad ao seu arquivo Gemfile.

source 'https://rubygems.org'
source 'https://rails-assets.org'

gem 'rails', '4.2.0'
gem 'sass-rails', '~> 5.0'
gem 'uglifier', '>= 1.3.0'
gem 'ember-rails'
gem 'ember-source', '~> 1.9.0'
gem 'rails-assets-jquery'

group :development, :test do
  gem 'test_squad'
end

Para gerar o esqueleto do projeto, execute o comando rails generate.

$ rails generate test_squad:install --framework ember
    create  test/javascript/unit
    create  test/javascript/unit/router_test.js
    create  test/javascript/routes
    create  test/javascript/routes/.keep
    create  test/javascript/components
    create  test/javascript/components/.keep
    create  test/javascript/views
    create  test/javascript/views/.keep
    create  test/javascript/models
    create  test/javascript/models/.keep
    create  test/javascript/test_helper.js
   gemfile  group :development, :test
    append  Gemfile
   gemfile  rails-assets-qunit
    append  Gemfile
    source  https://rails-assets.org
     exist  test/javascript
    create  test/javascript/test_squad.rb

O generator irá detectar se você está usando RSpec ou TestUnit e irá gerar o diretório apropriado.

Você precisa fazer uma única configuração no arquivo (test|spec)/javascript/test_helper.js: modificar o namespace de sua aplicação, atribuindo-o à variável App.

//= require application
//= require_self
//= require_tree ./components
//= require_tree ./models
//= require_tree ./routes
//= require_tree ./unit
//= require_tree ./views

// Set the application.
App = SquadSample;

// Set up Ember testing.
App.rootElement = '#ember-testing';
App.setupForTesting();
App.injectTestHelpers();

A gem test_squad possui integração com asset pipeline, então você pode usar CoffeeScript, se esta for a sua praia.

Você pode executar os testes de duas maneiras: no seu navegador ou no terminal.

Executando testes no navegador

Primeiro, configure o arquivo config/routes.rb para adicionar a rota de testes. Isso só é necessário se você estiver usando a rota catch-all. No Ember, isso será necessário se você usar a opção de history.pushState.

Rails.application.routes.draw do
  root 'ember#bootstrap'
  get :tests, to: 'test_squad#tests' unless Rails.env.production?
  get '/*path' => 'ember#bootstrap'
end

Para acessar o testes em seu navegador, acesse o endereço http://localhost:3000/tests.

Rodando testes do Ember no navegador

Executando testes no terminal

Para executar o testes no terminal iremos usar o Phantom.js. Para instalar no Mac, use o Homebrew.

$ brew install phantomjs

Agora use o comando rake test_squad.

Rodando testes do Ember no terminal

Estendendo o QUnit

Se você quer ter uma série de métodos adicionais para testar sua aplicação, experimente o ember-qunit. Ele vem com funções para testar módulos de componentes, modelos, e muito mais.

Para instalá-lo, adicione a gem rails-assets-ember-qunit ao seu Gemfile. Instale esta nova dependência com o comando bundle install.

source 'https://rubygems.org'
source 'https://rails-assets.org'

gem 'rails', '4.2.0'
gem 'sass-rails', '~> 5.0'
gem 'uglifier', '>= 1.3.0'
gem 'ember-rails'
gem 'ember-source', '~> 1.9.0'
gem 'rails-assets-jquery'

group :development, :test do
  gem 'test_squad'
  gem 'rails-assets-qunit'
  gem 'rails-assets-ember-qunit'
end

Depois, altere seu arquivo test_helper.js para carregar e configurar o Ember-QUnit.

//= require application
//= require ember-qunit/dist/globals/main
//= require_self
//= require_tree ./components
//= require_tree ./models
//= require_tree ./routes
//= require_tree ./unit
//= require_tree ./views

// Set the application.
App = SampleApp;

// Set up ember-qunit
emq.globalize();
App.Resolver = Ember.DefaultResolver.extend({namespace: App});
setResolver(App.Resolver.create());

// Set up Ember testing.
App.rootElement = '#ember-testing';
App.setupForTesting();
App.injectTestHelpers();

Pronto! Agora você já pode usar funções como moduleFor, moduleForComponent e moduleForModel.

Instalando o Ember Inspector

Se você pretender desenvolver com Ember, lembre-se de usar o Chrome com a extensão Ember Inspector. Com ela você consegue inspecionar os objetos criados, ver tempos de renderização, além de muito mais.

Ember Inspector

Finalizando

Com a crescente necessidade de se ter muitos clientes para um produto (como a versão web, mobile e, dependendo do tipo de produto, CLI), existe uma tendência de se ter uma única API que todos estes clientes possam usar. E o Ember que se tornar o framework definitivo para a criação de aplicações (cliente?) web.

Será que ele vai conseguir?