Buenas,
Sigo con mi entrenamiento en Ruby y estoy haciendo un mini proyecto Rails que consume una gema que a su vez recubre un servicio web (Stormpath). No hay BBDD.
Como conté en un anterior tema vengo del mundo Java y estoy acostumbrado a trabajar con componentes JSF y Primefaces que se recargan o interactúan con el backend vía AJAX de manera automática. Tras ver que en Rails no existen librerías/gemas similares opté por utilizar Bootstrap como librería de apoyo para componentes.
Tengo muy encaminado el proyecto pero tengo una duda y tras mucho leer por internet no termino de quitármela. Os pongo en situación: Tengo un formulario de login inicial que en caso de ser positivo accedería a una nueva página de la aplicación y en caso negativo mostraría en una capa de la misma página del formulario un mensaje de error. welcome.html.erb: Formulario de login de aplicación con remote a true
[code]
<%= form_tag @login, class:"form-horizontal form-signin top-margin40", id:"formSingin", role:"form", remote:true do %>
... Campo usuario
... Campo contraseña
<button type="submit" class="btn btn-primary pull-right"></button>
[/code]
En el controlador tengo el método login que se encarga de comprobar el usuario y contraseña cosumiendo la gema de Stormpath y donde al final tengo:
[code]
if @account.errors.empty?
session[:user] = @account format.js { render :js => "window.location.href='" + directories_path + "'"}
else
format.js
end
[/code]
Si surge algún problema en el login ejecutará por defecto login.js.erb donde tengo el código JS que visualiza una capa con el error oportuno.
Y la duda viene aquí, si el login ha ido OK y quiero hacer una redirección desde el controller tras una petición con remote a true debo de hacerla utilizando código JS. A mi parecer, lo veo un poco chapucero, ¿no existe alguna manera mejor o más correcta de hacerlo?
Pregunta BONUS: ¿Que frameworks/librerías JS soléis utilizar que se integren bien con Rails (a parte del propio CoffeScript)?
Hola Fernando!
Yo asi a bote pronto veo un poco lioso como lo estas haciendo, si pones mas codigo que mojo mas en decirte, pero por el momento te contesto asi un poco en abstracto:
- @login y @account a que clase pertenecen cada una? Normalmente se suele usar el mismo modelo tanto en el formulario como en las dos acciones del controlador que estaras usando (new & create). Aunque no uses DB yo seguiria usando modelos (Mira este link http://railscasts.com/episodes/219-active-model)
- El formulario deberias usar form_for si es uno de tus modelos. El principal motivo: te generara los valores automaticamente para los inputs (text, texarea, etc)
- Deberias usar algo como if @account.valid? en tu caso, pega mas y se lee mejor.
En cuanto a tu respuesta, es muy sencillo, te lo digo asi a ojo sin comprobarlo pero creo que te deberia valer:
if @account.valid? # mejor que 'errors.empty?'
session[:user] = @account
format.js { render :js => "window.location.href='" + directories_path + "'"}
else
redirect_to root_path # O la ruta que tu gustes.
# Le manda un (302 Found) con la url de la redireccion en la cabeceras HTTP
end
Gracias por tus consejos Ivan, sé que no es lo más correcto como lo estoy haciendo y poco a poco voy puliendo mis errores.
Utilizo ActiveModel en otros puntos de la aplicación donde trabajo con objetos del "modelo", en este caso, he puesto el formulario de login así para ilustrar mejor mi duda y creo que no lo he conseguido XD
Mi duda inicial viene de tras realizar una petición con remote: true la respuesta debe de ser en formato JS ya sea directamente código en el controlador como por ejemplo, format.js { render :js => "window.location.href='" + directories_path + "'"} o si en el método del controlador no indicamos nada necesitamos un archivo nombre_metodo.js.erb que será tomado por defecto.
¿Hay alguna manera de redireccionar tras petición AJAX más elegante que la que indico?
ANEXO: He probado a utilizar el método "redirect_to root_url" como me indica Ivan y esto muestra el log.
Redirected to http://localhost:3000/
Completed 302 Found in 1102ms (ActiveRecord: 0.0ms)
Started GET "/" for 10.0.2.2 at 2015-01-15 08:47:02 +0000
Processing by AccountsController#welcome as JS
Rendered accounts/welcome.html.erb within layouts/application (5.3ms)
Rendered layouts/_modal.html.erb (0.4ms)
Se puede ver como por debajo se realiza la redirección pero no ocurre nada en el navegador, se mantiene en la vista donde se realizó la petición AJAX.
Vale, creo que me aventure en contestarte antes de enteder del todo tu situacion. Tu la peticion la haces por AJAX, con lo que el redirect que te dije no va a servir para nada (si serviria si fuera HTTP de toda la vida, en este caso la peticion ajax recuperara la pagina a la que es redireccionada, pero como no es javascript, no vale para nada..), asi que respecto a mi anterior mensaje.. ni caso!
Por lo que en definitiva solo se me ocurre la solucion que tu empleas u otra aun mas fea, que seria redireccionar siempre a tu codigo js y alli calcular si redireccionas o muestras mensaje de error. Si quieres escuchar esta version dimelo, pero vamos que a mi me convence todavia menos..
Si te sirve de consuelo, lo unico que se me ocurre (que no es mucho) para dejarlo un poco mas bonito es que uses esta sintaxis..
format.js { render js: "window.location.href=#{ directories_path }" }
Básicamente lo hago con Ajax por varios motivos:
1 - La más importante es porque me van a preguntar si se puede hacer con Ajax :P Estoy en proceso de "formación" con Rails y le estoy buscando las vueltas.
2 - Tengo hecha una versión alternativa con jQuery.post + JSON
3 - Utilizando Ajax puedo mostrar un mensaje de error de login en la misma página del formulario de login sin necesidad de recargar la página (Devolviendo código JS en la response).
4 - Derivado de la 1, quería probar como van las peticiones remote y los archivos necesarios .js.erb. Lo siguiente que tengo pendiente es mirar CoffeScript en mayor profundidad.
Sigo con mi entrenamiento en Ruby y estoy haciendo un mini proyecto Rails que consume una gema que a su vez recubre un servicio web (Stormpath). No hay BBDD.
Como conté en un anterior tema vengo del mundo Java y estoy acostumbrado a trabajar con componentes JSF y Primefaces que se recargan o interactúan con el backend vía AJAX de manera automática. Tras ver que en Rails no existen librerías/gemas similares opté por utilizar Bootstrap como librería de apoyo para componentes.
Tengo muy encaminado el proyecto pero tengo una duda y tras mucho leer por internet no termino de quitármela. Os pongo en situación: Tengo un formulario de login inicial que en caso de ser positivo accedería a una nueva página de la aplicación y en caso negativo mostraría en una capa de la misma página del formulario un mensaje de error.
welcome.html.erb: Formulario de login de aplicación con remote a true
[code]
<%= form_tag @login, class:"form-horizontal form-signin top-margin40", id:"formSingin", role:"form", remote:true do %>
... Campo usuario
... Campo contraseña
<button type="submit" class="btn btn-primary pull-right"></button>
[/code]
En el controlador tengo el método login que se encarga de comprobar el usuario y contraseña cosumiendo la gema de Stormpath y donde al final tengo:
[code]
if @account.errors.empty?
session[:user] = @account
format.js { render :js => "window.location.href='" + directories_path + "'"}
else
format.js
end
[/code]
Si surge algún problema en el login ejecutará por defecto login.js.erb donde tengo el código JS que visualiza una capa con el error oportuno.
Y la duda viene aquí, si el login ha ido OK y quiero hacer una redirección desde el controller tras una petición con remote a true debo de hacerla utilizando código JS. A mi parecer, lo veo un poco chapucero, ¿no existe alguna manera mejor o más correcta de hacerlo?
Pregunta BONUS: ¿Que frameworks/librerías JS soléis utilizar que se integren bien con Rails (a parte del propio CoffeScript)?
Gracias y un saludo.
14/01/2015 17:19
Yo asi a bote pronto veo un poco lioso como lo estas haciendo, si pones mas codigo que mojo mas en decirte, pero por el momento te contesto asi un poco en abstracto:
- @login y @account a que clase pertenecen cada una? Normalmente se suele usar el mismo modelo tanto en el formulario como en las dos acciones del controlador que estaras usando (new & create). Aunque no uses DB yo seguiria usando modelos (Mira este link http://railscasts.com/episodes/219-active-model)
- El formulario deberias usar form_for si es uno de tus modelos. El principal motivo: te generara los valores automaticamente para los inputs (text, texarea, etc)
- Deberias usar algo como if @account.valid? en tu caso, pega mas y se lee mejor.
En cuanto a tu respuesta, es muy sencillo, te lo digo asi a ojo sin comprobarlo pero creo que te deberia valer:
if @account.valid? # mejor que 'errors.empty?'
session[:user] = @account
format.js { render :js => "window.location.href='" + directories_path + "'"}
else
redirect_to root_path # O la ruta que tu gustes.
# Le manda un (302 Found) con la url de la redireccion en la cabeceras HTTP
end
15/01/2015 09:52
Utilizo ActiveModel en otros puntos de la aplicación donde trabajo con objetos del "modelo", en este caso, he puesto el formulario de login así para ilustrar mejor mi duda y creo que no lo he conseguido XD
Mi duda inicial viene de tras realizar una petición con remote: true la respuesta debe de ser en formato JS ya sea directamente código en el controlador como por ejemplo, format.js { render :js => "window.location.href='" + directories_path + "'"} o si en el método del controlador no indicamos nada necesitamos un archivo nombre_metodo.js.erb que será tomado por defecto.
¿Hay alguna manera de redireccionar tras petición AJAX más elegante que la que indico?
ANEXO: He probado a utilizar el método "redirect_to root_url" como me indica Ivan y esto muestra el log.
Redirected to http://localhost:3000/
Completed 302 Found in 1102ms (ActiveRecord: 0.0ms)
Started GET "/" for 10.0.2.2 at 2015-01-15 08:47:02 +0000
Processing by AccountsController#welcome as JS
Rendered accounts/welcome.html.erb within layouts/application (5.3ms)
Rendered layouts/_modal.html.erb (0.4ms)
Se puede ver como por debajo se realiza la redirección pero no ocurre nada en el navegador, se mantiene en la vista donde se realizó la petición AJAX.
15/01/2015 10:31
Por lo que en definitiva solo se me ocurre la solucion que tu empleas u otra aun mas fea, que seria redireccionar siempre a tu codigo js y alli calcular si redireccionas o muestras mensaje de error. Si quieres escuchar esta version dimelo, pero vamos que a mi me convence todavia menos..
Si te sirve de consuelo, lo unico que se me ocurre (que no es mucho) para dejarlo un poco mas bonito es que uses esta sintaxis..
format.js { render js: "window.location.href=#{ directories_path }" }
A ver si a alguien se le ocurre algo mejor..
15/01/2015 17:08
Saludos.
20/01/2015 14:54
¿Por qué no simplemente hacer un post del formulario de forma síncrona?
20/01/2015 17:31
1 - La más importante es porque me van a preguntar si se puede hacer con Ajax :P Estoy en proceso de "formación" con Rails y le estoy buscando las vueltas.
2 - Tengo hecha una versión alternativa con jQuery.post + JSON
3 - Utilizando Ajax puedo mostrar un mensaje de error de login en la misma página del formulario de login sin necesidad de recargar la página (Devolviendo código JS en la response).
4 - Derivado de la 1, quería probar como van las peticiones remote y los archivos necesarios .js.erb. Lo siguiente que tengo pendiente es mirar CoffeScript en mayor profundidad.
Gracias por vuestros comentarios.