Chamadas Ajax simples no Rails

Vamos supor que você tenha um menu básico como este

Visão feia

E você deseja que o estado Premium (qualquer atributo booleano) mude ao clicar para um determinado local (qualquer objeto).

Uma maneira realmente legal de fazer esse tipo de coisa é por meio de chamadas AJAX, que é alterar o estado da árvore DOM sem recarregar a página.

Configurando tudo

O que faço é escrever algumas rotas específicas para isso e só quero que essas rotas sejam acessíveis apenas por meio de AJAX e AJAX. O seguinte resolve

#config/routes.rb
Rails.application.routes.draw do
class OnlyAjaxRequest
def matches?(request)
request
.xhr?
end
end
#rest of the routes
end

Voltaremos a isso mais tarde.

Agora veja a vista

#app/views/show.html.erb
...
<a href="" data-remote=true id="unique_id" class="premium-state"><%= local.premium %></a>
...

e observe o campo data-remote, isso é fundamental para o que queremos. Diz ao controlador que, quando clicamos neste link, não queremos que ele seja enviado para o procedimento regular de formato HTML. Em vez disso, queremos o JS.

No controlador (lembre-se de que esta é apenas uma maneira rápida de escrever o método do controlador, mas você deve verificar, por exemplo, se o update_attributesfoi bem sucedido

#app/controllers/locals.rb
def set_premium
local = Local.find params[:local_id]
if local.premium #if local is premium, we set it to false
local.udpdate_attributes(:premium => false)
@message = "true"
else
#same thing for premium false
end
respond_to
do |format|
format
.js
end
end

Veja a linha format.js aí? Diz ao controlador: ‘não renderize a resposta html (a visão), em vez disso renderize a resposta javascript.

Agora, quando você responde com HTML, você precisa ter uma visão no formato html. Agora você precisa de um com extensão.js.erb

#set_premium.js.erb
$
("#unique_id").text("<%= j @message %>");

Este código será executado quando você clicar no unique_idlink da visualização.

Mas espere…

Ainda não definimos o caminho para esta ação.

#config/routes.rb
resources
:locals do
post
'set_premium' => 'locals#set_premium', constraint: OnlyAjaxRequest.new

Aí está. A constraintparte indica que esta chamada deve ser feita através de AJAX.

Como chamo esta rota

Você percebeu que o <a>elemento não tinha um campo href? Eu faço isso através de Javascript

#app/assets/javascripts/locals.js.coffee
$
(".premium-state").on "click", ->
local_id
= $(this).attr('id');
$
.ajax {
url
: ROUTE_TO_YOUR_ACTION
type
: 'post'
dataType
: 'script'
success
: () ->
}

onde ROUTE_TO_YOUR_ACTIONé o caminho que o rake routescomando abre para aquela ação específica do controlador.
Algumas observações:

  • o campo dataType da chamada AJAX é ‘script’. Pense nisso como o AJAX solicitando um arquivo de script e executando-o.
  • a sucessfunção não possui instruções. As instruções vão na visualização Javascript para o método que você solicitou!
  • o typecampo deve consistir na nomenclatura da rota personalizada.

aaaaaae terminamos.

E eu acho que é isso. Seu botão AJAX deve estar funcionando agora.

Sinta-se à vontade para apontar qualquer inconsistência no artigo, para que eu possa corrigi-la / explicá-la.