Vamos supor que você tenha um menu básico como este
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_attributes
foi 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_id
link 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 constraint
parte 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 routes
comando 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
sucess
função não possui instruções. As instruções vão na visualização Javascript para o método que você solicitou! - o
type
campo 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.