El siguiente attempt_login
método se llama usando Ajax después de que se envía un formulario de inicio de sesión.
class AccessController < ApplicationController
[...]
def attempt_login
authorized_user = User.authenticate(params[:username], params[:password])
if authorized_user
session[:user_id] = authorized_user.id
session[:username] = authorized_user.username
flash[:notice] = "Hello #{authorized_user.name}."
redirect_to(:controller => 'jobs', :action => 'index')
else
[...]
end
end
end
El problema es que eso redirect_to
no funciona.
Como resolverias esto ?
ruby-on-rails
ajax
ruby-on-rails-3
redirect
Misha Moroshko
fuente
fuente
render :js => "window.location = '#{jobs_path}'"
jobs_path
básicamente tan rígido como la URL? Si la URL cambia, también lo hará el nombre de la ruta, a menos que tenga mucho cuidado. Otra alternativa seríarender js: "window.location = '#{polymorphic_path(@job.class)}'"
utilizar la ruta ingeniosa calculada basada en el modelo de trabajo. Esto solo funciona si sus rutas son ingeniosas y usan convenciones de nomenclatura estándar que se alinean con sus modelos. (O si especifica nombre_del_modelo en sus modelos de modo que generen los nombres de las rutas correctas.)Existe una forma muy sencilla de mantener el flash para la próxima solicitud. En tu controlador haz algo como
flash[:notice] = 'Your work was awesome! A unicorn is born!' flash.keep(:notice) render js: "window.location = '#{root_path}'"
Se
flash.keep
asegurará de que el flash se mantenga para la próxima solicitud. Entonces, cuandoroot_path
se procese, mostrará el mensaje flash dado. Rails es increíble :)fuente
Creo que esto es un poco mejor:
render js: "window.location.pathname='#{jobs_path}'"
fuente
render js: "window.location.pathname = #{jobs_path.to_json}"
En una de mis aplicaciones, uso JSON para llevar a cabo la redirección y los datos de los mensajes flash. Se vería así:
class AccessController < ApplicationController ... def attempt_login ... if authorized_user if request.xhr? render :json => { :location => url_for(:controller => 'jobs', :action => 'index'), :flash => {:notice => "Hello #{authorized_user.name}."} } else redirect_to(:controller => 'jobs', :action => 'index') end else # Render login screen with 422 error code render :login, :status => :unprocessable_entity end end end
Y un ejemplo simple de jQuery sería:
$.ajax({ ... type: 'json', success: functon(data) { data = $.parseJSON(data); if (data.location) { window.location.href = data.location; } if (data.flash && data.flash.notice) { // Maybe display flash message, etc. } }, error: function() { // If login fails, sending 422 error code sends you here. } })
fuente
Combinando la mejor de todas las respuestas:
... if request.xhr? flash[:notice] = "Hello #{authorized_user.name}." flash.keep(:notice) # Keep flash notice around for the redirect. render :js => "window.location = #{jobs_path.to_json}" else ...
fuente
def redirect_to(options = {}, response_status = {}) super(options, response_status) if request.xhr? # empty to prevent render duplication exception self.status = nil self.response_body = nil path = location self.location = nil render :js => "window.location = #{path.to_json}" end end
fuente
No quería modificar las acciones de mi controlador, así que se me ocurrió este truco:
class ApplicationController < ActionController::Base def redirect_to options = {}, response_status = {} super if request.xhr? self.status = 200 self.response_body = "<html><body><script>window.location.replace('#{location}')</script></body></html>" end end end
fuente