ruby on rails - example - Rieles que no vuelven a cargar la sesión en la publicación de ajax
ruby and rails documentation (3)
Estoy experimentando un problema muy extraño con Rails y ajax usando jQuery (aunque no creo que sea específico de jQuery).
La aplicación My Rails usa el almacén de sesiones de cookies, y tengo un inicio de sesión muy simple que establece la identificación del usuario en la sesión. Si user_id no está configurado en la sesión, redirige a una página de inicio de sesión. Esto funciona sin problemas. Las solicitudes JQuery GET también funcionan bien. El problema es cuando hago una POST jQuery - el navegador envía la cookie de sesión bien (confirmé esto con Firebug y volcando request.cookies en el registro) pero la sesión está en blanco, es decir, la sesión es {}.
Estoy haciendo esto en mi application.js:
$(document).ajaxSend(function(e, xhr, options) {
var token = $("meta[name=''csrf-token'']").attr(''content'');
xhr.setRequestHeader(''X-CSRF-Token'', token);
});
y aquí está mi publicación de muestra:
$.post(''/test/1'', { _method: ''delete'' }, null, ''json'');
que debería llegar a este método de controlador (_method: delete):
def destroy
respond_to do |format|
format.json { render :json => { :destroyed => ''ok'' }.to_json }
end
end
Al mirar el registro y usar Firebug, puedo confirmar que el valor de cookie correcto se envía en el encabezado de solicitud cuando se produce la publicación ajax, pero parece que en algún momento Rails pierde este valor y pierde la sesión, por lo que redirige al inicio de sesión página y nunca llega al método.
He intentado todo lo que puedo pensar para depurar esto, pero estoy llegando a la idea de que esto podría ser un error en Rails. Estoy usando Rails 3.0.4 y jQuery 1.5 si eso ayuda. Me resulta muy extraño que las solicitudes de envío y publicación regulares (es decir, no ajax) funcionen, y las solicitudes de ajax funcionan sin problemas, solo son las publicaciones ajax las que no lo hacen.
¡Cualquier ayuda para tratar de arreglar esto sería muy apreciada!
Muchas gracias,
Dave
Encontré otro caso:
¿Ha configurado el ''csrf_meta_tag'' en su archivo de diseño de la aplicación?
en mi caso, no puse esa etiqueta, y encontré el mismo problema con el tuyo.
¡Y después de configurar el csrf_meta_tag en la aplicación / views / layouts / application.html.erb, todo funciona bien!
¡Por fin, gracias por ayudarme a encontrar la causa raíz! muchas gracias ~
Para eso está el adaptador oficial de rieles jquery-ujs en la serie 3.0. Sin embargo, debe recordar mantenerla actualizada al actualizar versiones de rieles.
Para mí, actualizar de 3.0.3 a 3.0.8.rc4 también significaba obtener manualmente el archivo src/rails.js
del repositorio vinculado.
Dado que Rails 3.1 finalmente hizo el cambio a jQuery, las cosas deberían actualizarse automáticamente en el futuro a través de la gema jquery-rails cuando se actualicen los rieles (y utilizando la canalización de activos incorporada de 3.1)
Voy a responder mi propia pregunta ya que he logrado averiguar qué estaba pasando. Lo publicaré aquí en caso de que sea útil para cualquier otra persona.
Después de investigar más, descubrí que el código que se suponía debía establecer el encabezado de solicitud con el token CSRF, no. Este fue el código original:
$(document).ajaxSend(function(e, xhr, options) {
var token = $("meta[name=''csrf-token'']").attr(''content'');
xhr.setRequestHeader(''X-CSRF-Token'', token);
});
Lo que sucedía era que este código no estaba configurando el encabezado, Rails recibía una solicitud de Ajax, el token no coincidía y estaba restableciendo la sesión. Esto solía generar un error de ActionController :: InvalidAuthenticityToken (supongo que habría detectado esto antes si se hubiera producido un error ... bueno), pero desde Rails 3.0.4 ahora simplemente reinicia silenciosamente la sesión.
Entonces, para enviar el token en el encabezado, tienes que hacer esto (muchas gracias a esta maravillosa publicación de blog ):
$.ajaxSetup({
beforeSend: function(xhr) {
xhr.setRequestHeader(''X-CSRF-Token'', $(''meta[name="csrf-token"]'').attr(''content''));
}
});
Y ahora todo funciona como debería. Lo cual es bueno.