Siete reglas para ser un programador efectivo
Phillip Chu da las que entiende son las siete reglas principales para ser un programador efectivo. Habrá que ponerlo en la lisa de buenos propósitos para año nuevo...
Phillip Chu da las que entiende son las siete reglas principales para ser un programador efectivo. Habrá que ponerlo en la lisa de buenos propósitos para año nuevo...
No hay mucho más que añadir.
En el post anterior de la serie, vimos cómo crear el modelo de la aplicación (en nuestro caso una clase que modele el objeto de negocio "regalo"), dejando que fuera el propio framework el que mapeara en ese objeto la estructura de la tabla previamente creada en la base de datos.
Dicho de forma un poco menos "rimbombante", al generar la clase Regalo, ActiveRecord se encarga de crear los objetos de negocio correspondientes (en este caso Regalo) y hacer todo lo necesario para que ese objeto sea persistente, conectándolo con la tabla regalos. Para ello, es necesario que el nombre que se le va a asignar al modelo sea el singular del nombre que tiene la tabla en la base de datos. Es decir, que si la tabla se llama regalos, el objeto de negocio se deberá llamar Regalo. Si la tabla se llamara coches, el objeto de negocio se debería llamar Coche. Siempre y cuando queramos que la creación del modelo sea automática, claro está.
Pero Rails es un framework cuyo punto fuerte no es precisamente la internacionalización, por lo que es posible que sea necesario configurar la aplicación para definir la correspondencia entre un sustantivo singular y su plural. Por, ejemplo, y sin probarlo, se me ocurre que camiones / Camion podría ser problemático.
Esa definición de las correspondencias entre un singular y un plural se puede realizar en el archivo environment.rb, que se encuentra en la carpeta config de la aplicación. En ese archivo hay una sección, que por defecto está comentada, en la que se pueden añadir tantas pluralizaciones como se considere necesario, utilizando para ello la clase Inflector (en realidad un singleton de la misma). Por ejemplo:
En todo caso, ¿sería ésta la mejor solución posible?. Bueno, la filosofía detrás de RoR consiste, entre otras cosas, en dar más importancia a la convención que a la configuración. Por tanto, siempre sería preferible evitar (no sólo por cuestiones metafísicas, sino también por comodidad) el tener que realizar configuraciones complejas para las aplicaciones.
Entonces, ¿cuál sería la convención?. Pues en general, se podría considerar lo siguiente:
Visto, por supuesto, de forma muy simplificada, y obviando que la convención se puede (y se debería) extender a algunos nombres más, como el nombre de las columnas de una tabla, y el nombre que se utiliza para presentar esas columnas cuando se hace scaffold, por ejemplo.
De todas formas, en caso de duda, no está mal utilizar una herramienta como el "pluralizador" de nuby on rails, que genera una posible colección de nombres a partir de uno dado.
Pues ya sólo falta probar la instalación por completo generando el modelo para la aplicación e intentando conectar a la misma. Lo primero será, por tanto, generar el modelo.
Como puede verse en la siguiente imagen, la estructura del proyecto es clara y bien organizada. Cada cosa está en su sitio.
El siguiente paso, es generar el controlador:
Para tener una aplicación mínimamente funcional, en la que están implementadas ya las cuatro operaciones básicas (alta, baja, modificación y consulta) tan sólo hay que editar el controlador de mi aplicación, regalo_controller.rb, y añadir una línea:
¡Y ya está!. Alta, baja, modificación y consulta, en dos minutos. Sobre decir que ahora es cuando debe comenzar el trabajo de verdad, pero ya tenemos un prototipo visible, a los pocos minutos de comenzar el desarrollo. ¿Somos ágiles o no?.
Para comenzar a introducir registros, hay que atacar la url http://localhost/test/regalo/new, y comenzar a toquetear:
Resumiendo: he instalado Rails (media hora más o menos), he instalado MySQL (un poco más largo, por los problemas con las herramientas de administración, pero en total ha sido una hora), he compilado el binding para MySQL (varias horas de google y unos minutos de resolución) y he realizado la primera iteración del desarrollo propiamente dicho (¡cinco minutos!).
Ahora empieza lo bueno...
Este paso ha sido el de resolución más corta, pero el de investigación previa a la solución más larga. Dicho de otra forma, horas de google, para encontrar una solución que se tarda un minuto en aplicar.
Por ahora, he instalado Ruby on Rails y MySQL en el ordenador, y he creado la base de datos con la tabla que voy a necesitar.
Ahora tengo que configurar la aplicación RoR para que utilice MySQL. Para ello, hay que editar el fichero correspondiente: /Users/ctarda/RoR/TestBlog/config/database.yml
Ahora viene la parte complicada. Si yo generase (como así hice) el modelo de aplicación en este momento, e intentase ejecutarla, obtendría un error ya que tal y como está todo, Rails no es capaz de conectar con la base de datos. ¿Por qué?. Porque no hay ningún binding para MySQL instalado.
Para instalar el binding, tendría que cambiar a la carpeta /usr/lib/ruby/gems/1.8/gems/mysql-2.7 y compilarlo (sudo make; sudo makeinstall). El problema es que no compila, y devuelve un error "can't find ruby headers".
Tras horas, repito, horas de google, encontré este post en el que explican brevemente que mi problema puede venir por la combinación Mac OSX 10.4.3 y XCode 2.2. La solución pasa por vincular las cabeceras del Ruby universal a las del ruby para powerpc. Sí, para mí también es chino. Y siento no poder ser más conciso en este punto, pero para mí tanto el problema como la solución al mismo están bordeando el mundo de la "magia".
El caso es que una vez aplicado ese parche ( cd /usr/lib/ruby/1.8/powerpc-darwin8.0;
sudo ln -s ../universal-darwin8.0/*), ya sí he podido compilar el binding de MySQL.
Ahora ya puedo comenzar el desarrollo en sí. Pero en el siguiente post.
La instalación de MySQL debería haber sido un paso más de la preparación del entorno, sin mayor importancia en teoría, pero al final ha sido la única parte verdaderamente dolorosa del proceso. En realidad, no ha sido la instalación en sí, sino la puesta en marcha de la base de datos y su integración con el RoR.
Continuamos con la instalación del entorno de desarrollo en el punto en el que nos quedamos en el post anterior.
El primer paso será descargar el instalador de MySQL, y ejecutarlo.
Si se quisiera que la base de datos se arrancara automáticamente al arrancar el sistema, habría que ejecutar también el instalador de MySQL Startup Item, que se incluye en el paquete.
Como indica la documentación, para que la instalación se pueda realizar, es necesario que exista en el sistema un usuario que se llame mysql, usuario que parece ser ya existe a partir de la versión 10.4.2 de Mac OSX, por lo que en mi caso, no ha sido necesario crearlo.
Una vez instalada la base de datos, habrá que arrancarla:
Si se quisiera parar:
A partir de este punto supongo que todo lo que voy a contar hay que tomarlo con precaución. Me explico. Las herramientas propias de MySQL para administrar la base de datos, como MySQL Administrator no han funcionado nada bien. Tampoco CocoaMySQL. Utilizando el administrador he podido crear usuarios de la base de datos, pero no tablas, y utilizando CocoaMySQL sólo he podido conectarme a la base de datos con el usuario anónimo. Doy por hecho que los problemas vienen por algún error en el proceso que voy a describir. Si alguien lo ve claro, por favor, que deje un comentario explicando cómo se debería hacer correctamente.
Bien, retomamos el proceso tras la instalación y el arranque de la base de datos. El primer paso va a ser crear el usuario root de MySQL:
Tras varios intentos, he conseguido arrancar MySQLAdministrator y conectar a la base de datos como root. Momento que voy a aprovechar para crear un usuario para los proyectos RoR (el usuario será ruby, y el password rails, impresionante despliegue de originalidad):
A continuación, creo el esquema para mi proyecto, que he llamado wishlist. Y creo la tabla para los datos, tabla que he llamado regalos. No he sido capaz de crear la tabla utilizando ninguna de las herramientas para administrar MySQL, por lo que después de muchos intentos, he terminado por ir a la solución rápida pero segura: logarme "a mano" en mysql desde el terminal (como el usuario rails), y crear la tabla haciendo un CREATE TABLE.
Para que la aplicación RoR pueda acceder sin problemas a los datos de la tabla, ésta debe tener una clave primaria (ojo, es importante hacerla AUTO_INCREMENT). La estructura de la tabla será:
Es importante fijarse en el nombre de la tabla: regalos. En el próximo post veremos el porqué de la importancia de ese nombre. Pero antes de eso, tendremos que configurar Rails para que pueda conectar con la base de datos MySQL. Y eso sí que ha sido un grano en el culo...
No sé muy bien cuánto hay de moda en Rails. Se habla mucho de lo rápido que puede ser el desarrollo utilizando este framework, de lo buena que es su implementación del modelo-vista-controlador, de lo sencillo que es el lenguaje... demasiadas cosas como para no probarlo.
Por eso, he decidido desarrollar una aplicación sencilla escrita en Ruby on Rails. La aplicación me va a permitir administrar mi lista de regalos para navidad. No la lista de los regalos que yo voy a hacer, sino de los que quiero que me hagan (así que, quien corresponda, que vaya tomando nota...). El desarrollo, no podría ser de otra manera, va a ser iterativo, de forma que comenzaré por hacer lo mínimo imprescindible para poder dar visibilidad, y a partir de ahí pretendo ir enriqueciendo la aplicación con todo lo que necesitará tener: autentificación de usuarios, AJAX (pensé que nunca escribiría ese palabro en este blog), regalos asignados a miembros de una lista de "regaladores" que también sea administrable... El paquete completo, por decirlo de alguna forma.
Pero lo primero que hace falta es un entorno de desarrollo. En este caso, la máquina en la que va a estar corriendo el servidor va a ser mi adorado Mac Mini (1.42 GHz y 512 MB RAM; Mac OSX 10.4.3). El servidor web a utilizar pretendo que sea el Apache que está instalado en el sistema, en vez del servidor propio de Rails, porque por una parte me siento cómodo configurando el Apache, y por otro lado no he leído cosas muy buenas de WEBrick (que así se llama). Además, el ordenador tiene instaladas las XCode Developer Tools (versión 2.2), requisito indispensable para que el "tinglado" funcione (y posteriormente, un grano en el culo a la hora de hacer el binding con la base de datos, como se verá).
Comenzamos. Abróchense los cinturones, y todas esas cosas.
Lo primero que hay que hacer es descargar algún paquete con Ruby on Rails, como por ejemplo este paquete, realizado por Tony Arnold. Por cierto, el procedimiento de instalación es muy similar al explicado en este post del propio Tony Arnold.
Una vez descargado el paquete, hay que proceder a instalarlo:
Posteriormente, hay que actualizar las gems:
Hay que tener en cuenta que el usuario con el que se está logado normalmente no tiene permisos suficientes para actualizar las gems. De ahí el tener que hacer un cambio temporal de usuario al root (sudo), que pedirá la contraseña de dicho usuario.
El proceso de actualización de las gemas es sencillo aunque el feedback del mismo puede considerarse más bien escaso. Como para muchas otras cosas, vigilar el uso de CPU suele dar más pistas sobre lo que está pasando que el propio feedback del proceso. Por cierto, hay que aceptar todas peticiones que se hacen durante el proceso de actualización. Calculo que, en mi caso, la actualización se realizó en unos 5-6 minutos.
Bien, una vez actualizadas las gemas, creamos una aplicación de prueba (no tan de prueba en este caso, ya que es sobre la que voy a realizar el desarrollo). Si todo se genera sin problemas, se podrá suponer que vamos por el buen camino:
Como se puede ver en la imagen, creo una carpeta llamada RoR en el raiz de mi usuario, y posteriormente, tras cambiar a esa carpeta, genero una aplicación llamada TestBlog (mal nombre, lo sé, pero ya no tiene remedio). Una vez concluya la generación de archivos (son bastantes) se podría arrancar el servidor "incorporado" de la siguiente forma:
Cosa que yo no voy a hacer, ya que, como ya he dicho con anterioridad, pretendo que el servidor a utilizar sea el Apache que incorpora el sistema. Pero antes de configurar Apache para que mi aplicación Rails funcione correctamente, hay que dar los permisos necesarios a la misma.
El problema es que Apache es un proceso propiedad del usuario www, pertenenciente al grupo www, por tanto tendré que asignar los archivos de mi aplicación a ese grupo. Igualmente, tendré que asignar permisos de escritura a los logs:
Esto empieza a ir por buen camino. Ahora hay que configurar Apache. Lo primero que habrá que hacer es añadir el módulo fast_cgi al archivo de configuración (/etc/http/httpd.conf):
También hay que incluir los Aliases de la aplicación (en la sección <IfModule mod_alias.c>):
Ahora, hay que editar el fichero .htaccess de la carpeta donde esté instalada la aplicación Rails (en mi caso /Users/ctarda/RoR/TestBlog). La línea:
debe cambiar a (nótese el cambio de cgi a fast cgi)
Además, hay que añadir estas líneas:
Ya estamos terminando. Sólo falta arrancar Apache:
y atacar la aplicación generada:
Si has llegado hasta este punto, enhorabuena (por aguantar despierto sobre todo). Ya has configurado Apache como servidor para tus aplicaciones Ruby on Rails. Pero por ahora no hemos creado más que el esqueleto de una aplicación que, obviamente, no hace nada de nada.
Para poder seguir avanzando, tendremos que instalar una base de datos, y comenzar a desarrollar nuestra aplicación. La base de datos que he elegido ha sido MySQL (porque es la que está instalada en el servidor de "producción" que voy a utilizar). Y con esa elección es donde han comenzado los problemas, problemas que veremos en el siguiente post, pero que se resumen con la siguiente frase: el paquete que he instalado no incluye un binding para MySQL, binding que no puedo instalar por un fallo en la configuración de las XCode Tools 2.2.
Pero eso lo veremos en el siguiente post.