Rails e Ajax: realizando requisições remotas sem recarregar a página

em Desenvolvimento, Ruby.

Você certamente já visitou um site em que partes dele se atualizaram sem recarregar a página. Por exemplo: você preencheu um formulário e, quando clicou em enviar, viu a resposta de sucesso quase que instantaneamente.


Essa técnica é implementada mais popularmente utilizando
Ajax (Asynchronous Javascript and XML), tecnologia que basicamente nos permite realizar algumas ações de update da página assincronamente em background.

Com isso conseguimos ter páginas mais dinâmicas e que consomem menos requisições dos servidores, poupando recursos e aumentando a eficiência.

Para a nossa alegriaRuby on Rails e Ajax são super amigos e, por isso, implementar Ajax no Rails é uma tarefa simples.

Não precisamos ter que escrever vários arquivos diferentes de javascript para que as operações funcionem porque ganhamos um Ajax estruturado e fácil de manipular de Rails. Nesse artigo vamos ver como implementar um formulário de modo que ele não precise recarregar a página quando for submetido. Vamos lá?

Primeiro precisamos fazer o setup inicial da nossa aplicação Rails. Como esse não é o nosso foco aqui, vou somente mostrar os comandos para fazer isso

$ rails new formajax

Agora dê um bundle para instalar as gems

$ cd formajax
$ bundle install

Para testar, inicie um servidor rails

$ bundle exec rails s

Entre no seu browser e digite o endereço do localhost:3000. Se tudo deu certo você verá a seguinte imagem:

rails_5

 

Como você pode perceber, eu estou usando Rails 5.0.0.1. Agora que terminamos o nosso setup inicial, vamos criar nosso MVC para representar nosso formulário. Como eu disse, para simplificar, nossa página terá apenas um formulário de cadastro de uma pessoa com os seguintes campos:

  • Nome
  • Email

Vamos então primeiro criar o nosso model. Não precisamos nos preocupar em configurar um banco de dados porque vamos usar o padrão do Rails que já vem configurado, o sqlite. Para criar um model no Rails digite o seguinte comando na raiz do seu projeto

$ rails generate model person name:string email:string
=> Running via Spring preloader in process 7901
  	invoke  active_record
  	create	db/migrate/20160817005523_create_people.rb
  	create	app/models/person.rb
 	 invoke	test_unit
  	create  	test/models/person_test.rb
  	create  	test/fixtures/people.yml

Agora temos que executar uma migração de banco para criar nossa tabela

$ rails db:migrate
== 20160817005523 CreatePeople: migrating =====================================
-- create_table(:people)
   -> 0.0008s
== 20160817005523 CreatePeople: migrated (0.0009s) ============================

Uma vez que temos uma tabela, vamos criar nosso controller people. Vamos ter as actions index (que mostrará todas as nossas pessoas e onde terá um formulário para criar novas) e create que será a action que irá responder nossa requisição ajax e de fato criar uma nova pessoa.

# app/controllers/people_controller.rb
 
class PeopleController < ApplicationController
 
  def index
	@person = Person.new
	@people = Person.all
  end
 
  def create
	@person = Person.new(person_params)
	@person.save
 
	redirect_to people_path
  end
 
  private
 
  # strong parameters
  def person_params
	params.require(:person).permit(:name, :email)
  end
end

Para que nosso controller possa receber requisições, precisamos informar para o Rails que ele existe. Para isso temos que alterar nosso arquivo routes.rb que fica no diretório config. Adicione a seguinte resource no mesmo:

# app/config/routes.rb
 
resources :people, only: [:index, :create]

O próximo passo é criar nossas views. Como html e css não é o nosso foco nesse artigo. Para não estender muito, não usarei nenhuma formatação, mas fique à vontade para adicionar o Locastyle, por exemplo, no seu código. Primeiro vamos criar a view index.html.erb que é onde ficará todos os nossos dados. Para isso crie uma nova pasta dentro da pasta views com o nome people e em seguida crie um arquivo com o nome index.html.erb. Nosso código vai ficar assim:

# app/views/people/index.html.erb
<%= form_for(@person) do |f| %>
 <%= f.label :name %>
 <%= f.text_field :name %>
 <%= f.label :email %>
 <%= f.text_field :email %>
 <%= f.submit 'Salvar' %>
<% end %>
 
<table>
 <thead>
  <tr>
   <th>Nome</td>
   <th>Email</td>
  </tr>
 </thead>
 <tbody>
  <% @people.each do |person| %>
  <tr>
   <td><%= person.name %></td>
   <td><%= person.email %></td>
  </tr>
  <% end %>
 </tbody>
</table>

Estamos utilizando um helper do Rails para gerar o nosso form que é o form_for e criamos uma tabela que imprime na tela todas as pessoas salvas no banco. Com isso já temos tudo configurado e podemos executar nossa aplicação. Ao fazermos isso, a seguinte tela deve aparecer:

form

Como podemos perceber, não temos nenhuma pessoa salva no banco ainda. Preencha o nome e o email e clique em salvar. Você pode ver que a pessoa que acabamos de adicionar apareceu na tabela de pessoas logo abaixo do formulário.

Mas para fazer isso acontecer, no nosso controller nós tivemos que redirecionar novamente para a nossa página index logo após salvar a pessoa no banco. Esse redirecionamento nada mais é do que se estivéssemos digitando no navegador o nosso endereço de acesso da action index que é localhost:3000/people.

Para não ter mais que fazer esse redirecionamento ao salvarmos uma nova pessoa, vamos fazer com que o nosso formulário realize requisições Ajax.
Para isso, faça a seguinte alteração na formulário da view index:

# app/views/people/index.html.erb
 
<%= form_for(@person, remote: true) do |f| %>
…

O parâmetro remote: true que estamos passando para o método form_for do nosso helper, informa que queremos que nosso formulário realize requisições Ajax ao invés de utilizar as requisições normais do browser. Agora que nosso form realiza requisições Ajax, então não precisamos mais fazer o redirecionamento na nossa action create, por isso vamos deletar aquela linha do nosso controller:

# app/controllers/people_controller.rb
 
def create
	@person = Person.new(person_params)
	@person.save
  end

Estamos prontos para testar novamente. Recarregue a página, crie uma pessoa e veja o que acontece. Nada, não é mesmo? Pois é, como estamos fazendo requisições em background e não estamos fazendo nenhum redirecionamento na nossa action create, temos a impressão de que nada aconteceu. Porém, se você olhar no log, verá que uma nova pessoa foi salva no banco. O nosso problema aqui é que não tivemos nenhuma resposta do servidor e por isso realmente nada irá acontecer do nosso lado.

Para resolver esse problema, precisamos fazer criar uma view javascript que contenha os dados da nova pessoa e as alterações necessárias para mostrá-la na tela e, também, programar o controller para que ele saiba que deve nos responder um javascript ao invés de um html. Como estamos no Rails 5, precisamos inserir a seguinte gem no nosso gemfile:

# Gemfile
 
gem 'responders', '~> 2.3'
 

Sem essa gem não temos acesso ao método respond_to, que é onde iremos informar ao controller que ele deve responder tanto html quanto javascript, dependendo do tipo da view. De um bundle para instalar e faça a seguinte alteração no controller

# app/controllers/people_controller.rb
 
class PeopleController < ApplicationController
  respond_to :js, :html
 
  def index
…

Agora que nosso controller já sabe como responder nossas requisições corretamente, crie a seguinte view javascript na pasta people que criamos anteriormente:

# app/views/people/create.js.erb
 
var tableRef = document.getElementById('people').getElementsByTagName('tbody')[0];
var newRow   = tableRef.insertRow(tableRef.rows.length);
var newCell  = newRow.insertCell(0);
var cell_text  = document.createTextNode('<%= @person.name %>')
newCell.appendChild(cell_text);
newCell  = newRow.insertCell(1);
cell_text  = document.createTextNode('<%= @person.email %>')
newCell.appendChild(cell_text);

Vocês podem ver que esse é um javascript bem simples e que somente adiciona uma nova linha na nossa tabela com o nome e o email da pessoa que acabou de ser criada. Essa variável @person é justamente a da action create. Agora sim, estamos realmente prontos para criar uma nova pessoa sem ter que recarregar a página. Legal, não é?

Pronto, agora você já sabe como enviar requisições Ajax no Rails. É mais simples do que parece, não? Caso necessário, você pode acessar o projeto na minha conta do github.
Vou deixar aqui também uma app bem legal que estamos desenvolvendo na empresa, em nosso tempo livre, que se chama niceretro e é toda baseada em requisições Ajax.

Sinta-se livre para perguntar ou deixar comentários. Até a próxima! :)

Você também pode gostar