En esta nueva revisión del SudokuOnRails vamos a incluir un sistema de registro y alta de usuarios, lo cual nos va a llevará a tratar materias que no habíamos tratado hasta ahora
- Instalar un plugin de Rails suministrado por terceros (
acts_as_authenticated) - Crear una base de datos y hacer que nuestra aplicación acceda a ella
Como siempre, tenéis disponible la aplicación online en SudokuOnRails.com y el código fuente está disponible aquí
Pero antes de entrar en materia tenemos algo pendiente actualizarnos a la última versión de Ruby on Rails desde hace mucho, así que empezaremos con el proceso de actualización…
Actualizar a Rails 1.0
Si venimos usando una versión antigua de Rails la actualización resulta prácticamente imprescindible, debido a la gran cantidad de nuevas funcionalidades introducidas en las versiones más recientes. Por suerte, la versión de Rails con la que veníamos trabajando hasta ahora era la 0.14, de forma que el proceso de actualización es trivial. Nos vamos al directorio padre del directorio raíz de la aplicación y escribimos
cp -r sor-4.0 sor-5.0
rails sor-5.0
Invocando otra vez a Rails sobre el árbol de directorios de nuestra aplicación, éste generará varios scripts y archivos de configuración nuevos. Aunque no se sobreescriben los ficheros con clases Ruby y plantillas que ya tengamos en nuestra aplicación, sí que se modifican varios ficheros que habíamos tenido que personalizar (Rails nos avisará de ello): en concreto, se trata de routes.rb , config/environment.rb, config/environments/development.rb, y los public/dispatch.fcgi y public/dispatch.cgi. Será necesario contrastar estos ficheros con la versión anterior y adaptar las diferencias (en Mac OS X esto puede hacerse visualmente usando FileMerge.app, que viene incluída con XCode). Tras examinar los cambios, decidimos que sólo nos interesa conservar routes.rb y borrar el nuevo index.html, y ya tenemos la aplicación funcionando otra vez tal y com la dejamos pero migrada a Rails 1.0.
Una última nota: no olvidemos que hay que editar .htaccess y modificar la línea donde se invoca dispatch.cgi y cambiarlo por dispatch.fcgi. Esto no nos afectará en principio durante el desarrollo, pero lo notaremos (¡y mucho!) cuando subamos nuestra aplicación a nuestro hosting favorito
Tras esto, podemos comprobar que nuestra aplicación funciona igual que antes.
Instalación de un plugin
Para continuar necesitamos tener disponible un cliente de Subversion en nuestro sistema de desarrollo. Nosotros, que desarrollamos con Mac OS, hemos usado la versión de Fink pero si estás en Windows tendrás que instalar otro Por supuesto, si estás en Linux probablemente tienes ya un cliente svn o sabes cómo instalarlo (si no, siempre puedes dejar un comentario a esta entrada de la bitácora y veremos qué se puede hacer).
El sistema de plugins de Rails tiene su propio gestor de repositorios, muy al estilo de RubyGems, CPAN o PEAR. Para ver qué repositorios de plugins tenemos disponibles en cualquier momento podemos hacer
ruby script/plugin discover
Con esto Rails se conectará a http://wiki.rubyonrails.org/rails/pages/Plugins y tomará nota de todas aquellas URLs que aparezcan en esta página y que parezcan repositorios de Subversion, asumiendo que contienen plugins instalables. Tras esto podemos hacer
ruby script/plugin list
y nos irá mostrando los plugins disponibles en los repositorios que acabamos de agregar automáticamente. No hay que preocuparse si aparecen mensajes de error emitidos por el cliente de Subversion, serán debidos a que alguno de los repositorios listados en la página del wiki que mencionábamos antes no se encuentra disponible. En este caso el proceso continuará con el resto de repositorios, ignorando los contenidos del repositorio problemático.
Tras esta operación, se nos muestra un listado con los plugins disponibles. Nosotros instalaremos el siguiente
ruby script/plugin install acts_as_authenticated
lo que creará el directorio vendor/plugins/acts_as_authenticated
Si examinamos este nuevo directorio, veremos que contiene un generador que realiza una función parecida al script/generate estándar de Rails. El sistema de plugins, en definitiva, no es más que una forma estándar de distribuir extensiones a Rails de una manera simple y organizada. En este caso el plugin acts_as_authenticated actúa generando código para nosotros (como veremos en un momento) pero otros plugins, como por ejemplo el cada vez más popular engines extienden Rails de una manera mucho más profunda modificando clases del core de Rails durante la inicialización de nuestra aplicación web, usando el mecanismo que ya hemos visto en una entrada anterior
Basta ya de filosofar. El siguiente paso es utilizar el generador, cosa que haremos en tres etapas.
ruby script/generate authenticated usuario cuenta
Este generador creará el modelo para nuestros usuarios en la BD, que se almacenará en una tabla llamada usuarios (y por tanto su modelo se llamará Usuario), y que queremos gestionar desde un controlador llamado cuenta. Se generan automáticamente todos los ficheros necesarios, incluyendo, como es habitual, casos de prueba.
También generaremos el código necesario para enviar notificacines por correo, que veremos en detalle más adelante.
ruby script/generate authenticated_mailer usuario
Por último, haremos que Rails nos genere el script necesario para generar el esquema requerido en la base de datos
ruby script/generate authenticated_schema crea_tabla_usuarios
Se crea el esquema en db/migrate/001_crea_tabla_usuarios.rb
Migraciones
Si has tenido la experiencia de trabajar antes con bases de datos con aplicaciones desplegadas en servidores en producción, entonces conocerás el problema que supone para el desarrollador tener en cuenta las diferencias entre el esquema de la base de datos con la que trabaja durante el desarrollo y el de las bases de datos de producción, esquema al puede que tenga que regresar temporalmente para, por ejemplo, perseguir algún problema. Hay que andar creando y borrando bases de datos y tablas, añadir, quitar campos… y además eso contando con que tu script SQL de definición del esquema lo tengas bajo control de versiones… Otro problema habitual es que en control de versiones solamente has venido guardando las modificaciones al esquema «oficial» de la base de datos y en un momento dado quieres construir la base de datos desde cero para una nueva instalación, así que te toca crear el esquema y aplicar mano a mano todos los sucesivos parches con modificaciones hasta llegar a la versión deseada.
Las migraciones son la respuesta a estos problemas al estilo Rails. Consisten, básicmente, en definir el esquema de la base de datos no con sentencias DDL de SQL (CREATE TABLE ..., etc) sino directamente con código Ruby que es traducido convenientemente al dialecto SQL del motor de la base de datos con la que trabajes (lo cual es otra ventaja, pues tu código de creación del esquema no depende de un fabricante concreto). Cada vez que haces una modificación al esquema tienes que definir una migración la cual especifica los cambios necesarios en la base de datos (y los necesarios para deshacer dichos cambios, de ser posible). Si durante el desarrollo has ido modificando el esquema de tu base de datos usando migraciones, con un sólo comando podrás actualizar cualquier base de datos a la última versión de esquema, o bien regresar de un esquema posterior a uno anterior. Veamos cómo.
El generador ha creado el fichero db/migrate/001_crea_tabla_usuarios.rb El prefijo 001 se ha asignado porque hasta ahora no teníamos ninguna migración definida, así que ésta será nuestra primera «revisión» del esquema. El resto del nombre es una descripción escogida por nosotros que, deseablemente, dará una pista de las modificaciones que incluye este esquema. Si editamos este fichero veremos que tiene esta pinta:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
class CreaTablaUsuarios < ActiveRecord::Migration # modify the table name for now, until I can figure out how to set it w/ the generator def self.up create_table "users", :force => true do |t| t.column "login", :string, :limit => 40 t.column "email", :string, :limit => 100 t.column "crypted_password", :string, :limit => 40 t.column "salt", :string, :limit => 40 t.column "activation_code", :string, :limit => 40 # only if you want t.column "activated_at", :datetime # user activation t.column "created_at", :datetime t.column "updated_at", :datetime end end def self.down drop_table "users" end end |
No es muy difícil imaginarse el cometido de cada sentencia. Armados con este archivo que nos ha generado autmáticamente Rails, podremos crear la tabla simplemente invocando la migración con rake. Por cierto que, dado que hemos creado el modelo usuario tendremos que ajustar nuestra tabla para que se llame usuarios en vez de users (en la sentencia create_table...).
Pero antes de ejecutar la migración, ¡tenemos que crear una base de datos contra la que trabajar!
Conectando Rails a la base de datos
Rails puede funcionar con muchas bases de datos distintas: PostgreSQL, DB2, Oracle, SQLite… y nuestra favorita desde hace mucho, MySQL. Si no tienes instalado aún este motor de bases de datos y trabajas bajo Windows, aquí encontrarás cómo hacerlo Nosotros en nuestros ejemplos trabajaremos con la consola de MySQL. Nuestro cometido será crear una base de datos MySQL y definir un usuario y clave con el que podamos acceder a ella.
mysql -h localhost -u root -p
mysql>create database sudokudb_dev;
mysql>grant all privileges on sudokudb_dev.* to 'usr_sudoku'@'localhost'
->identified by 'martingala';
Ya que estamos, también crearemos las bases de datos dbsudoku_test y dbsudoku_prod y realizamos la misma operación. ¿Por qué es esto así? Ya ha sido explicado en innumerables tutoriales en la red (como este) y a estas alturas todo el mundo lo sabrá, pero hay que decirlo: Rails tiene tres modos posibles de funcionamiento: desarrollo, producción y pruebas, siendo la diferencia entre los tres (al menos la que nos incumbe ahora) la base de datos a la que se conectan. De esta manera el desarrollador puede fácilmente escoger cualquiera de las tres en cualquier momento para realizar su trabajo.
Tras esto, editamos el fichero config/database.yml e introducimos la información necesaria para que Rails se conecte a cada base de datos según el entorno de funcionamiento
development:
adapter: mysql
database: dbsudoku_dev
host: localhost
username: usr_sudoku
password: martingala
test:
adapter: mysql
database: dbsudoku_test
host: localhost
username: usr_sudoku
password: martingala
production:
adapter: mysql
database: dbsudoku_devel
host: miservidor.produccion.com
username: usr_sudoku
password: martingala
(En el fichero que genera Rails 1.0 por defecto hay un montón de ejemplos de configuración para otros adaptadores disponibles de base de datos, podremos borrarlos sin mayor problema—a no ser claro, que usemos una base de datos que no sea MySQL)
Y esta es toda la información que necesita Rails para trabajar con la base de datos, así que ya podemos crear el esquema del que hablábamos antes simplemente ejecutando el comando de migración
rake migrate
Vemos que aparecen en nuestra base de datos la tabla usuarios (que era lo que queríamos) y además una tabla nueva llamada schema_info que simplemente guarda el número de la última migración aplicada y que será lo que usen el script de migración para saber qué migraciones tiene que aplicar en cada momento para actualizar un esquema (por tanto, nosotros no tenemos que hacer nada con ella). Ya podemos continuar desarrollando nuestra aplicación.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
mysql -u usr_sudoku -p sudokudb_dev
Enter password:
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 50 to server version: 4.1.12-standard
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql> show tables;
+------------------------+
| Tables_in_sudokudb_dev |
+------------------------+
| schema_info |
| usuarios |
+------------------------+
2 rows in set (0.00 sec)
mysql> desc schema_info;
+---------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+---------+------+-----+---------+-------+
| version | int(11) | YES | | NULL | |
+---------+---------+------+-----+---------+-------+
1 row in set (0.00 sec)
mysql> desc usuarios;
+------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------------+--------------+------+-----+---------+----------------+
| id | int(11) | | PRI | NULL | auto_increment |
| login | varchar(40) | YES | | NULL | |
| email | varchar(100) | YES | | NULL | |
| crypted_password | varchar(40) | YES | | NULL | |
| salt | varchar(40) | YES | | NULL | |
| activation_code | varchar(40) | YES | | NULL | |
| activated_at | datetime | YES | | NULL | |
| created_at | datetime | YES | | NULL | |
| updated_at | datetime | YES | | NULL | |
+------------------+--------------+------+-----+---------+----------------+
9 rows in set (0.00 sec) |
Editando el código de nuestra aplicación
El segundo paso que hacíamos para generar el código del plugin era
ruby script/generate authenticated usuario cuenta
El código generado para nosotros es bastante ordenado y viene ampliamente comentado, así que una buena recomendación (aunque seas nuevo en Rails) es repasar el código de los ficheros y tratar de entender cómo funcionan.
Como habíamos comentado, ahora tenemos una nueva clase modelo (usuario) y un nuevo controlador, cuenta Les echaremos un vistazo.
Modelo usuario
Esta clase (models/usuario.rb) es la que realiza la tarea de encriptado de claves, además del mapeo con la tabla de la base de datos. Como suele ser habitual en estos casos la clave cifrada no es reversible así que la técnica para comprobar si la clave de un usuario es correcta, ésta se cifra y se busca en la base de datos un usuario con el mismo valor de clave cifrada. En ningún momento se usa la clave en claro, que no está almacenada en la base de datos.
Por defecto el plugin no genera código para verificar a los usuarios mediante direcciones de correo. Como deseamos tener esta funcionalidad, tendremos que prestar atención en nuestro repaso del código a los comentarios en el código que nos indican las modificaciones necesarias.
En la definición de la clase Usuario, quitamos el comentario en :before_create make_activation_code Lo que hará será generar un código de activación para cada objeto del modelo que creemos, invocadno la función make_activation_code al crear cada instancia de Usuario
self.authenticate, comentamos la línea find_by_login y descomentamos la inmediatamente superior,
@u = find :first, :select => 'id, salt', :conditions => ['login = ? and activated_at IS NOT NULL', login]@ |
Con esto un usuario sólo puede registrarse con éxito si introduce la clave correcta y ha efectuado la activación tras recibir el correo electrónico.
Quitaremos el bloque de comentario que rodea a las funciones activate y recently_activated?, las cuales modifican y consultan, respectivaamente, el estado de activación de un objeto de la clase usuario: los objetos recién creados estarán sin activar, y sólo pasarán a estado activado cuando el usuario pulse en el enlace que se le suministre por correo.
Por último, quitamos el comentario a la función make_activation_code, que es la que genera un token aleatorio difícil de adivinar.
Echando un vistazo al directorio de modelos, vemos que se han creado dos nuevas clases, usuario_notifier y usuario_observer De momento las dejaremos para más adelante…
Controlador para las cuentas de usuario
Nuestro controlador para las cuentas de usuario se llama CuentaController y se encuentra, cómo no, en app/controllers/
Al igual que con el modelo del usuario, vamos a repasar el archivo prestando atención a los comentarios para la funcionalidad de activación de cuentas por correo.
En el métodologin, quitamos el comentario en la línea
::ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS.update(:session_expires => 4.weeks.from_now) if params[:remember_me] |
quedando el código así
1 2 3 4 5 6 7 8 9 10 |
def login return unless request.post? ::ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS.update( :session_expires => 4.weeks.from_now) if params[:remember_me] self.current_usuario = Usuario.authenticate(params[:login], params[:password]) if current_usuario redirect_back_or_default(:controller => '/cuenta', :action => 'index') flash[:notice] = "Logged in successfully" end end |
El propósito de la modificación está claro: si el usuario escoge cierta casilla en el formulario de login (que más adelante también tendremos que añadir) se hace que la sesión sea válida durante cuatro semanas (por defecto, duraría hasta que el usuario cierre el navegador). Después se invoca el método de autenticación del modelo y, si tiene éxito, se redirige a la acción index del controlador.
Para concluir con el controlador, sólonos resta quitar el comentario al método activate. Este es el método que invocará el usuario cuando reciba el mensaje de correo de activación de cuenta (la URL que reciba será un enlace a la acción activate, usando como parámetro el token aleatorio generado por make_activation_code) La función simplemente busca elusuario que tiene ese token de activación y, si existe lo activa, tras lo cual las invocaciones al método login tendrán éxito.
Las vistas
Lo primero que nos encontramos es app/views/cuenta/index.rhtml, es decir la vista de la acción por defecto de nuestro controlador de cuentas de usuario. Curiosamente, el autor del plugin ha puesto ahí toda una poesía de Ellen P. Allerton. Nosotros seremos menos poéticos y nos limitaremos a poner un pequeño mensaje.
<% if current_usuario %>
Esta es la página del usuario <%= current_usuario.login %>
<% else %>
Regístrate para... para... ¡bueno, para algo!
<% end %>
Como vemos, en nuestra plantilla podemos acceder al usuario registrado con current_usuario (que valdrá @nil si no hay un usuario registrado)
El formulario que se muestra al usuario para registrarse en la aplicación (invocando el método login de nuestro controlador) es app/views/cuenta/login.rhtml, ahí tendremos que añadir el checkbox del que hablábamos antes para hacer que el registro sea persistente en nuestro navegador:
1 2 |
<p><label for="remember_me">Remember Me?</label> <%= check_box_tag 'remember_me', 1, true %></p> |
El último formulario que nos queda es app/views/cuenta/signup.rhtml, que no necesita modificaciones ni aporta nada nuevo.
Confirmación de cuentas de correo para la activación de usuarios
El mecanismo es sencillo: cuando el usuario se da de alta en el sistema, queremos enviarle un correo a la dirección que nos proporciona con una URL a la que tendrá que acceder para confirmar el alta y poder entrar en nuestra aplicación.
La forma en que el plugin realiza esta tarea es muy elegante y conviene dedicarle unas líneas.
En primer lugar, tenemos la clase UsuarioObserver (app/models/usuario_observer.rb) que es un Observer de ActiveRecord En breve, una clase llamada XXXObserver tendrá como misión vigilar cualquier cambio en cualquier instancia de la clase XXX descendiente de ActiveRecord, siendo ejecutados sus métodos según el carácter de la modificación. Podemos ver qué métodos hay disponibles en la documentacion oficial . Nosotros sólo estamos interesados en dos posibles alteraciones de una instancia de nuestra clase Usuario: la creación y la modificación de algún dato. En el primer caso enviamos el correo con los datos de alta y en el segundo enviamos un correo avisando que la cuenta se ha activado. Los métodos del API que nos interesa capturar son after_create y after_save.
En segundo lugar, tenemos la clase que sabe enviar correos electrónicos, nuestro UsuarioNotifier, que es un modelo (sin tabla asocida en la base de datos) que solamente dispone de dos métodos: signup_notificaction y activation los cuales preparan el correo electrónico y lo formatean según las vistas del directorio app/views/usuario_notifier Debemos configurar aquí lo que deseemos para nuesra aplicación, tanto el mensaje que envían las vistas como el asunto y el remitente, el nombr ey la URL de nuestra aplicación, etc.
¿Falta algo más? Pues casi nada más El mecanismo de ActionMailer es sencillo: cuando se invoca el método deliver_XXX de una clase que hereda de ActionMailer, Rails sabe que debe invocar el método XXX (en nuestro caso, tenemos deliver_signup_notification y deliver_activation, que se invoncan desde usuario_observer.rb, que dispararán a su vez los métodos signup_notification y signup_activation de nuestra clase UsuarioNotifier).
Lo único que queda por hacer es configurar ActionMailer con los datos necesarios para poder mandar correos electrónicos desde nuestro hosting, lo que se hace manera similar a un cliente de correo normal y corriente. Los pondremos en config/environment.rb, aunque podrían estar en config/environment/{development,production,test}.rb si quisiésemos tener valores distintos para los diferentes modos de funcionamiento de nuestra aplicación.
A nosotros nos bastará con modificar config/environment.rb
1 2 3 4 5 6 7 8 |
ActionMailer::Base.server_settings = { :address => "mail.sudokuonrails.com", :port => 25, :domain => "sudokuonrails.com", :user_name => "amapola", :password => "lindisima", :authentication => :login } |
Rematando la autenticación
El resto de la autenticación reside en lib/authenticated_system.rb, así que deberemos incluirlo en el controlador prnicipal de la aplicación
1 2 3 4 |
class ApplicationController < ActionController::Base include AuthenticatedSystem end |
Esta clase define los métodos auxiliares que usaremos en el resto de nuestra aplicación cuando queramos hacer alguna comprobación acerca del estado de login de un usuario. Así, logged_in? devuelve nil si no hay un usuario registrado, current_usuario devuelve el objeto del usuario, etc. Por último, define el método login_required que es el que pondremos en la cláusula before_filter de los controladores a los que queramos que sólo pueda acceder un usuario registrado.
En nuestro Sudoku On Rails queremos dos cosas: que los usuarios no puedan acceder al controlador de récords si no están registrados (aunque si que pueden jugar partidas al Sudoku de manera anónima). Esto lo conseguimos, como hemos dicho antes, con la siguiente sentencia en app/controllers/records_controller.rb
1 2 3 4 5 |
class RecordsController < ApplicationController model :tablero before_filter :login_required ... end |
Según la documentación de Rails , para hacer que se disparen nuestros observadores basta con añadirlos a la línea config.active_record_observers en config/environment.rb. Sin embargo, el autor del plugin, recomienda activar el observador simplemente de esta manera:
1 2 3 4 5 |
class ApplicationController < ActionController::Base include AuthenticatedSystem observer :usuario_observer end |
Según Rick si se hace de la primera manera el observador no sea ctiva correctamente cuando nuestra aplicación funciona en modo de desarrollo (debido a algún bug ignoto). Nosotros hemos constatado que, en efecto, el Observador se comporta de forma errática si se declara en config.active_record_observers. Un efecto colateral es que, al declarar el Observer en la línea de environment.rb, debería estar activo también si accedemos a nuestra aplicación via script/console, lo cual no ocurre con la técnica de Rick.
Hagamos algo con el usuario
Queremos que el usuario sepa en todo momento si está registrado o no, así como proporcionar un enlace para registrarse o darse de alta. Esto lo conseguiremos definiendo un componente
En el directorio components/ crearemos un subdirectorio llamado barralogin, y creamos un fichero llamado estadologin_controller.rb:
1 2 3 4 5 6 7 8 9 10 |
class Barralogin::EstadologinController < ActionController::Base include AuthenticatedSystem uses_component_template_root def dame_estado @usuario = current_usuario render(:layout => false) end end |
Y colgando de componentes/barralogin, un nuevo subdirectorio estadologin, con la vista dame_estado.rhtml:
<% if @usuario %>
Bienvenido, <%= @usuario.login %> | <%= link_to 'Salir', :controller => 'cuenta', :action => 'logout' %>
<% else %>
No estás registrado | <%= link_to 'Registro', :controller => 'cuenta', :action => 'login' %> | <%= link_to 'Alta', :controller => 'cuenta', :action => 'signup' %>
<% end %>
Por último, en views/layouts/application.rhtml añadiremos lo siguiente entre los divs de cabecera y menú:
<%= render_component(:controller => 'barralogin/estadologin',
:action => 'dame_estado') %>
Este pequeño componente consulta si tenemos algún usuario activo y, dependiendo del resultado, muestra una u otra línea bajo la cabecera de nuestra página. Sólo nos queda ya añadir la clase correspondiente en nuestra hoja de estilos public/stylesheets/default.css
#estadologin {
width: 640px;
margin: 0px;
font-size: 10px;
font-weight: normal;
clear: both;
padding: 0;
text-align: right;
}
Tareas pendientes
Con esto ya podemos dar por concluida la integración del sistema de autenticacón en nuestra aplicación, aunque debemos tener en cuenta que no hacemos en realidad nada con nuestro modelo de usuarios, sólo lo usamos para autenticar el controlador RecordsController de forma que un usuario no pueda acceder a él si no está registrado (pero si termina la partida sin registrarse, SudokuController lo redirigirá allí… ¿qué pasará?)
En la próxima iteración de SudokuOnRails, haremos más coss con los usuarios, tales como mantener una tabla con las mejores partidas de los usuarios, y que cada usuario pueda consultar los últimos resultados que ha obtenido. También deberemos traducir todos los mensajes, que aparecen en inglés. A falta de usar un sistema de internacionalización como Dios manda, nos conformaremos de momento con buscar todas las cadenas de los ficheros generados y la traduciremos al castellano.
Hay otros problemas más fastidiosos, como el hecho de que si tratamos de dar de alta un usuario dos veces, repetimos un email o las claves no coinciden (en definitiva, si la acción signup no puede validar el usuario introducido) los mensaje de error nos aparecen en inglés, porque provienen de las mismas tripas de ActiveRecord y sus validaciones (validates_uniqueness_of y sus amigos)
Todos estos problemas serán resueltos (o al menos lo intentaremos) en próximas revisiones de SudokuOnRails ¡Os espero!


March 6th, 2006 at 06:05 PM Es posible de manera sencilla manejar algo como un ACL bajo act_as_authenticated, para darle acceso solo a algunos usuarios que esten en cierto dominio?
March 7th, 2006 at 11:08 AM Gustavo, así a vuela pluma se me ocurre que puedes añadir una validación adicional al modelo del Usuario:
validates_format_of :email, :with => /.*@dominio.com/, :message => "Solo usuarios de dominio.com"March 7th, 2006 at 12:51 PM Me referia mas bien a un dominio de permisos. Probe anteriormente el user_engine, y me permitia de una manera hacer uso de RBAC, por asi decirlo, tambien con el gem auth_generator, podria hacer algo similar. Me preguntaba como seria una forma de añadirselo a act_as_authenticated.
March 7th, 2006 at 05:36 PM Leeeche, que currazo de post:D voy a probarlo y ya te cuento.
March 14th, 2006 at 05:35 AM Hola! Es una muy buena mejora!, enhorabuena por tu trabajo, sólo una matización, creo que estaría bien, que al igual que te permite registrarte, te permitiera recuperar la cuenta registrada, :)
March 14th, 2006 at 06:23 AM Neko: ¡eso queda apuntado para la v6!
March 16th, 2006 at 10:20 PM Hola, estoy probando el plugin y siguiendo tu manual para la instalacion me di cuenta que tenes un pequeño error. Cuando hablas de generar el schema, esta mal el generador ya que no existe "authenticated_schema" y lo que hay que utilizar es "authenticated_migration". Saludos, Ah.. exelente el trabajo