Showing posts with label Ruby. Show all posts
Showing posts with label Ruby. Show all posts

Tuesday, 22 May 2007

Active Record = Join Tables

En uno de los primeros POSTs de este blog, hablaba de las relaciones entre tablas a través de los modelos de ActiveRecord e intentaba (conseguía?)explicar un modo para entender como definir correctamente estas relaciones. Me gustaría ampliar un poco esto para analizar una de las relaciones que creo que no he tratado correctamente, las relaciones N a N a través de Join tables.

Estas relaciones se dan cuando tenemos dos tablas relacionadas entre si a través de una tercera tabla. En esta tabla, se suele sustituir la clave primaria por la unión de los índices de las dos tablas relacionadas, si bien esto no es obligatorio.

Rails permite definir estas relaciones de una manera muy sencilla usando en ambos modelos la relación has_and_belongs_to_many :tabla (vaya nombrecito). Usando esta sencilla fórmula, seremos capaces de acceder desde un objeto de uno de los modelos a la lista de elementos del otro modelo de una forma muy sencilla. Por ejemplo, si relacionamos Authors y Articles a través de la Join Table Publication, podremos hacer algo así.

autor = Author.find(:first)
lista_articulos = autor.articles

En lista_articulos tendremos un array de objetos Article que se han asociado a Author a través de la tabla Publication. Tendremos que seguir ciertas convenciones que rails nos indica como que el nombre físico de la join table este compuesto por los nombres de las tablas enlazadas en minúscula y en orden alfabético. Si queréis ver la especificación, visitad el API. Facil no???

Pero hay un problema. Imaginemos que esta tabla Publication tiene campos adicionales que no son los índices de las tablas referenciadas. Rails no nos pone ninguna pega para acceder a esta información. De hecho, la incluye en el array que hemos obtenido anteriormente. El problema es que estos campos son de solo lectura. No se pueden modificar. La aproximación que se tomaba era la utilización de delete para borrar una entrada antigua y del método push_with_attributes(object, attributes) para introducir una tupla nueva en la join table. PERO ESTE METODO ESTA DEPRECATED. NO LO USEIS.

Afortunadamente, este problema ya esta resuelto. El truco (no es un truco, pero vaya) es usar una doble relación has_many en ambas tablas a relacionar usando el modificador :through. Ah, y creando un nuevo modelo que nos identifique la join table. Esto es muchísimo mejor, ya que recuperamos toda la funcionalidad que nos proporciona el tener una tabla identificada por un modelo. También eliminamos la necesidad de llamar a la tabla con nombres raros (autor_articulo en el caso anterior)

Bueno, como definiríamos esto en la relación anterior???? Marchando.

class Author << ActiveRecord::Base
has_many :publications
has_many :articles, :through => :publications
end

class Publication << ActiveRecord::Base
belongs_to :author
belongs_to :article
end

class Article<< ActiveRecord::Base
has_many :authors
has_many :authors, :through => :publications
end

Que os parece??? tenemos ahora acceso a tooooodos los métodos de inserción, etc... De la tabla Publication y podemos trabajar de un modo mucho más sencillo.

Thursday, 17 May 2007

NetBeans 6 Preview Milestone 9

Como anunciaron en la JavaONE, ya tenemos disponible el Milestone 9 de NetBeans 6 con soporte Ruby, JRuby y Ruby on Rails. url.

En varios videos que han publicado en NetBeans.tv, he visto una integración de Rails muy avanzada. Llevaba tiempo esperando una versión estable para poder probarla y detallar como avanza esta nueva alternativa dentro de los IDEs para el desarrollo Rails.

En estos momentos estoy terminando de descargar el software (pesa unos 166 megas). En cuanto lo instale y lo pruebe, pondré un post comentando mis impresiones. De todas formas, si se confirma lo que mostraban estos videos, es un rival muy fuerte para Aptana. Muy, muy fuerte.

El link al software. http://bits.netbeans.org/download/6.0/milestones/latest/

Wednesday, 16 May 2007

Ruby on Rails VS JEE

Os acordais de los anuncios Mac VS PC de los tios gordo y bajito??? Pues aqui tenemos una versión del mismo enfrentando a RoR y JEE. Me ha echo muchísima gracia. Supongo que por el tiempo que me he pegado peleandome con JEE (Antes J2EE), sus config.xml, sus ear de 5 megas, etc... Espero que os guste tanto como a mi.

Wednesday, 9 May 2007

Active Record find

Actualmente me encuentro desarrollando una aplicación WEB que dispone de un API REST y una parte estándard. A la hora de desarrollar las consultas a los modelos, me he encontrado con que algunas de estas son muy complejas y tiendo a pensarlas en SQL directamente, ya que es un lenguaje que da un gran rendimiento y flexibilidad.

ActiveRecord::Base nos proporciona dos métodos para realizar estas consultas, find y find_by_sql. En el caso del segundo la opción está clara: insertar directamente el SQL que he pensado para obtener solo lo que yo quiero obtener y con el formato que yo necesito. En el caso del primero, solo con echar un vistazo al API podemos ver que tiene un gran número de posibilidades, parámetros, etc.. que lo convierten en una opción muy poderosa para realizar las consultas. Asi pues, me surge una duda ¿Cual de ellas usar?

Esta pregunta, que en principio parece muy sencilla, no lo es tanto. Si controlas SQL tenderás a hacer uso de find_by_sql ya que te abstraeras de aprender las opciones y posibilidades de ActiveRecord y trabajarás con algo conocido. Pero precisamente esto es algo que no deberíamos hacer. Bajo mi punto de vista, tendríamos que usar las ventajas que nos da Rails evitando usar SQL directamente.

Diseñamos la BD, definimos los modelos de las tablas, declaramos las relaciones entre ellos. CONTROLAMOS la estructura de nuestros datos. Imaginemos que tenemos una tabla Articles y otra tabla Tags. Definimos una relación n-to-n con sendas directivas :has_and_belongs_to. Bien, pues en el caso en que queramos obtener todas las tags de un artículo, podemos bien escribir un SQL que obtenga la información de las distintas tablas o podemos dejar hacer a ActiveRecord, ya que por el hecho de tener esta relación, es capaz de proporcionarnos esta información automáticamente con el siguiente código.

article = Article.find(article_id)
article.tags.each do |tag|
puts tag.tag_name
end

Mantenemos el código sencillo. Usamos los convencionalimos de Rails. Resulta extremadamente sencillo de interpretar. EVITAMOS MEZCLAR LENGUAJES.

Tuesday, 8 May 2007

Aptana (I) : Debug

Hace unas semanas, comentaba en una entrada del blog que me había decidido finalmente por el plugin Ruby in Steel para visual Studio. Bueno, pues desde hace muy poco tiempo, exactamente desde el 1/5/2007, tenemos disponible la primera versión de Aptana que integra RadRails. Si y no. De "serie" no incluye esta funcionalidad, pero es muy sencillo descargarnosla siguiendo los pasos que se indican en la página de descargas.

Las versiones night-build de este entorno que incluían RadRails era demasiado inestables para ser usadas para desarrollo, sobre todo la parte de Debug. Pero todo esto ha cambiado. Y de que manera!!! Me voy a atrever a afirmar que el debug de aplicaciones de Rails está casi conseguido al 100% en la versión actual de Aptana. Voy a enumerar las que, a mi modo de ver, son las principales funcionalidades de que disponemos para debug.

  • Botón Script/Console. Nos lanza una consola o símbolo de sistema dandonos acceso a todos los componentes de la aplicación. Imprescindible para debugear cuando estamos creando los Modelos. Podemos comprobar las relaciones que hemos establecido, el resultado de las consultas, como se producen las excepciones al intentar eliminar cuando tenemos recursos protegidos, etc... Todo aquel que se inicie en Rails tiene que pasar un tiempo con la consola para adaptarse al lenguaje y al API. Aptana nos permite realizarlo dentro del propio IDE, sin tener que tener varias consolas de sistema abiertas y lo que es más importante, pudiendo introducir pequeños scripts y ejecutarlos de vez sin tener que soportar el tedio de la consola de sistema.
  • Botón Debug. Le indicamos que nos lance un Debug de Ruby para nuestra aplicación. De este modo, nos abre la perspectiva de Debug permitiendonos poner puntos de ruptura, hacer una ejecución paso a paso, etc... Para poder hacer debug necesitamos tener instalado el gem ruby-debug. La siguiente imagen nos muestra la página de propiedades tal y como tiene que estar configurada.
Vemos que nos indica que tenemos que tener instalada la gem ruby-debug-ide. Con Ruby-gems podemos instalarla ejecutando gem install ruby-debug-ide

Esta es una captura de la perspectiva de Debug en Aptana con puntos de interrupción activados.

Espero con impaciencia que permitan poner puntos de interrupción, en definitiva debugear, no solo en el modelo y los controladores, sino también en las vistas. Hasta este momento, los archivos .rhtml no permiten activar los puntos de interrupción para ver paso a paso como se van generando. No obstante, la velocidad de carga del servidor interno es muy buena, la respuesta del entorno en debug inmejorable y la sensación general es que esto esta avanzando a pasos agigantados.

Voy a ir diseccionando poco a poco que añade esta versión de Aptana al desarrollo Rails. Espero que en cosa de unos meses, dispongamos de un IDE tan avanzado que el no usarlo sea casi pecado!!!!!!!!

Friday, 27 April 2007

AOP en Rails???? Marchando!!!!!!!

Observers. Si conoces como funciona AOP te vas a maravillar con lo sencillo que va a ser añadir control de aspectos a nuestras clases Model en Rails. De echo, si lo pensamos un momento es el punto más obvio del modelo Rails en el que añadir esta funcionalidad. Nos va a permitir añadir control a los puntos de entrada y salida de las operaciones CRUD que nos proporciona ActiveRecord::Base, es decir, new, create, update, delete, save.

Lo que nos propone ActiveRecord::Observer es el poder crear metodos que se ejecuten antes o después de las invocaciones a cada uno de estos métodos. La forma es muy sencilla. Estos son los pasos para hacer un log para cada operación de guardado. Haremos un pre-log y un post-log.

  1. Creamos una clase que herede de ActiveRecord::Observer y la nombraremos con el nombre del Modelo a observar seguido de Observer, es decir, si nuestro modelo es Shop la llamamos ShopObserver.
  2. Guardamos el archivo en la carpeta app\model con el nombre shop_observer.rb
  3. definimos un método before_save en el que ponemos la funcionalidad a ejecutar ANTES de guardar. En nuestro caso, el log.
  4. definimos un método after_save donde incluimos funcionalidad para DESPUES de guardar.
  5. Editamos el archivo config/environment.rb modificando la entrada config.active_record.observers = :shop_observer
El codigo fuente final

class ShopObserver < ActiveRecord::Observer def before_save(a_shop) a_shop.logger.info("PRE-LOG - Shop name = #{a_shop.name}") end def after_save(a_shop) a_shop.logger.info("POST-LOG - Shop name = #{a_shop.name}") end end Y ya esta todo. Ahora podemos ejecutar la consola del entorno con ruby script/console para testear lo que hemos creado. Si ejecutamos
shop = Shop.new(:name=>"ebay")
shop.save

vamos a ver que el archivo development.log va a contener dos entradas de log ejecutadas antes y después de llamar al método save.

Yo estoy cada vez más encantado con la funcionalidad que me proporciona este framework DE SERIE, y sin necesidad de añadirle plugins o librerías externas.


Thursday, 26 April 2007

Active Records (II)

Siguiendo con el manualillo que voy escribiendo sobre como entender el concepto de ActiveRecord, voy a poner una ayuda para entender mejor como se realizan relaciones. Las relaciones se establecen usando palabras clave y un punto de relación. El problema es con los puntos de relación. Según el tipo de relación tenemos que definirlo como plural o como singular. Alguien me djo una vez que lo que mas le gustaba de Ruby era el lenguaje en si, ya que se parece mucho al lenguaje natural. Estas son las formas de relacion posible.

  • Relaciones singulares
    • has_one :other
    • belongs_to :other
  • Relaciones plurales
    • has_many :others
    • has_and_belongs_to :others
Mejor todavía, vamos a verlas desde el punto de vista de un modelo entidad relacion.

  • One-to-One
    • has_one :other (TABLA REFERENCIADA)
    • belongs_to :other (TABLA CON LA FOREIGN KEY)
  • One-to-Many
    • has_many :others (TABLA REFERENCIADA)
    • belongs_to :other (TABLA CON LA FOREIGN KEY)
  • Many-to-Many (Join table)
    • has_and_belongs_to :others (AMBAS TABLAS REFERENCIADAS)
Siguiendo la guia que di en el anterior articulo podemos entender mejor las referencias que hacen las palabras reservadas. Solo queda un detalle más a esclarecer. el uso de singulares y plurales.

Nuestras tablas estan en plural, nuestras clases Model estan en singular (customers, Customer) y aqui, ¿Como la ponemos? pues depende. Nos tenemos que olvidar de la convención de nombrado de la BBDD y el Modelo y pensar como lo hariamos si tuvieramos que describirlo.

Ej.

En una relacion 1 a N entre unas tablas Writers - Novels la relación sería

class Writer
has_many :novels
end

class Novel
belongs_to :writer
end

Es un poco extraño ya que no tenemos una identificación directa para novels en las clases Model pero, ¿No os parece intuitivo? Este ejemplo es demasiado obvio, en otras ocasiones los elementos que almacenamos en las BBDD no son tan sencillos de identificar por sus referencias, pero creo que es suficientemente explicativo.

Wednesday, 18 April 2007

Debug con RadRails

Rails es genial...............hasta que entras en la fase de Debug. Llevo todo el día probando diferentes opciones para realizarlo. Hasta ahora, había usado RadRails como IDE y más o menos era suficiente. Pero hasta que no saquen la versión nueva ahora que se han integrado con Aptana el debug por defecto no funciona. He encontrado varias soluciones que voy a contar.

  • Configurar script/server como punto de Debug. Funciona, pero le cuesta un mundo arrancar el servidor (y digo un mundo por no decir una burrada).
  • Descargarte una night build de RadRails como plugin para Eclipse usando RDT. Funciona mucho mejor, más rápido y siempre engancha al llegar a los puntos de interrupción. Me ha parecido demasiado Buggy. Aún tienen que mejorar bastante.
  • Usar Ruby in Steel Personal Edition. Es un plugin para el Visual Studio 2005 que añade soporte Ruby y RoR. Es una version gratuita del mismo Software versión Developer y funciona bastante bien......salvo pq no me deja editar ficheros (estoy actualizando ahora mismo el Visual Studio con el SP1 para solucionar esto)
Creo que actualmente esta última será la mejor, por velocidad y pq esta basada en el VS2005. Si con el SP1 no me funciona voy a instalarme la versión en Inglés, pq estoy casi seguro que el problema viene por incompatibilidades de los editores por los paquetes de idioma instalados.

Bueno, no voy a desanimarme por esto!!!! Sigo opinando que Rails es muy interesante y las herramientas seguro que van a evolucionar a lo largo de los próximos meses que se prometen apasionantes.