Configurando o Ember.js no Rails
Leia em 5 minutos
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.
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
.
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
.
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.
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?