format internet:

…por favor espere (34% finalizado)…

Archivos para 'ruby on rails' Categoría


masochism: plugin para replicación master-slave en MySQL

Publicado por javier ramirez en Mayo 18, 2008

Recientemente me he encontrado con la necesidad de trabajar desde Rails contra una base de datos MySQL replicando en modo master-slave.

Replicación Master-Slave In a Nutshell:

La idea de montar un master-slave es tener la base de datos maestra para realizar las modificaciones a la base de datos, y usar la/las bases de datos esclavas para realizar las lecturas. De esta forma, las operaciones de lectura, que son las más habituales, se pueden balancear entre diferentes instancias de una base de datos.

Por otro lado, cada vez que se hace una modificación en la maestra, esta modificación se replica en las esclavas, de forma que los datos siempre están sincronizados.

Esta imagen del manual online de MySQL es muy explicativa

mysql master slave

Claramente este esquema nos puede ayudar mucho de cara a la escalabilidad de una aplicación, ya que la base de datos es uno de los cuellos de botella típicos.

Lo que necesitamos en este caso, es asegurarnos de que todas las operaciones de escritura van contra la conexión de la maestra, mientras que las lecturas van por una conexión esclava.

Una de las ventajas de usar un framework- en este caso Rails, pero podría haber sido cualquier otro- es que tu aplicación tiene una arquitectura bien definida. O al menos debería. Esto significa que al usar Rails tenemos bajo control las operaciones que se hacen contra la base de datos, con lo que identificar las de lectura y las de escritura debería ser simple. Si seguimos las reglas del framework, las operaciones contra la base de datos pasarán siempre por el modelo y por los métodos que AR nos proporciona.

Al final, el número de métodos que realmente acaban accediendo a la base de datos son más bien pocos, con lo que podríamos jugar un poco con el framework, establecer dos conexiones con la base de datos (una con la maestra, y otra con la esclava) y decidir qué conexión va a usar cada método. Así todos los métodos “find” y similares irían por la esclava, y los “delete”, “insert”, etc.. irían por la maestra.

Esto mismo es lo que el plugin masochism hace automáticamente por nosotros. El plugin viene de la mano del hiperproductivo Rick Olson.

Uno de estos días tendré que contar en más detalle cómo va, pero el resumen ejecutivo es que lo instalas, le añades una conexión master_connection en tu fichero database.yml, llamas a un método en uno de tus initializers… y te olvidas. A partir de ahí todo funciona de forma transparente (siempre que hayas configurado tu master/slave de MySQL previamente, claro).

De momento le he encontrado una única pega. Entre los métodos que se envían a la base de datos maestra no está el método “execute”, que es el típico método que sólo utilizas cuando quieres modificar algo en la base de datos. Sin ir más lejos, el (imprescindible) plugin Foreign Key Migrations usa ese método para crear las FK, por lo que si no nos aseguramos de que se usa la base de datos maestra, podemos tener problemas.

Le he mandado un parche (en realidad es añadir una palabra y una coma) a Rick , a ver si le parece apropiado incuírlo como parte del plugin.

update: y el patch ya ha sido incluído :)

Y a escalar!!

searchwords: scalability, mysql replication, master-slave, javier ramírez

Publicado en desarrollo, javier ramirez, ruby, ruby on rails, ruby on rails | Etiquetado: , , , , | 3 Comentarios »

Aptana RadRails. El libro… Mi libro ;)

Publicado por javier ramirez en Mayo 5, 2008

Ya va quedando menos para que se publique el libro de RadRails en el que llevo trabajando varios meses. Acabo de terminar los últimos cambios después de las revisiones técnicas y ya queda sólo la revisión de estilo de los últimos tres capítulos.

portada del libro

En la web de la editorial ya han creado la página para el libro, así que parece que esto ya no tiene marcha atrás (aunque el título todavía podría sufrir algún cambio)

La verdad es que tiene su aquel eso de ver tu nombre en la portada de un libro… y eso que al final no han escogido mi propuesta de foto para la portada ;)

mi propuesta de portada

searchwords: javier ramirez, radrails, aptana, aptana radrails book

Publicado en desarrollo, eclipse, javier ramirez, radrails, ruby, ruby on rails | Etiquetado: , , | 5 Comentarios »

madrid-rb el grupo de ruby (y ruby on rails) de madrid

Publicado por javier ramirez en Abril 22, 2008

Después de unos meses de silencio por overflow de actividades extraescolares, voy a intentar retomar el blog… aunque veremos lo que dura porque dentro de un par de días empiezo a dar clases otra vez.

Aprovecho la ocasión para anunciar la creación de madrid-rb, el grupo de ruby de madrid. Queremos organizarnos un poco y retomar las quedadas que se hacían hace tiempo, pero dándoles un carácter mensual. En concreto el último jueves de cada mes.

La idea es vernos, hacer comunidad, buscar puntos de encuentro comunes, dar alguna charlita ligera, juntarnos para hackear un poco y quizás crear alguna gema o algún plugin… y usarlo como excusa para salir un jueves al mes :p

La primera cita es este mismo jueves, a las 19:30, en el Starbucks de la calle Génova 4 en madrid.

El grupo se está organizando a través de este grupo de google. Además también tenemos un grupo creado en working with rails.

Y, lo anunciaré en la quedada del jueves, pero lo voy dejando ya por aquí, me han aprobado un proyecto en rubyforge para que podamos dejar el código que vayamos haciendo. Como puedes subir tus páginas estáticas y rubyforge mola, llevo idea de proponerlo para subir la home del grupo ahí.

Si no quieres perderte ninguna cita, hay disponible un calendario al que te puedes suscribir.

searchwords: madridrb, madrid, quedada, rubyforge, google groups

Publicado en conferencias, desarrollo, internet, javier ramirez, madrid, madridrb, ruby, ruby on rails | 1 Comentario »

Creación de plugins con rails

Publicado por javier ramirez en Noviembre 7, 2007

Si quieres desarrollar tus propios plugins para rails pero no tienes muy claro por dónde empezar, puede interesarte la charla que daré el viernes 23 de Noviembre en la conferencia rails 2007. Bajo el no demasiado inspirado título ‘Programa en Rails como si jugases con Lego’, presentaré los puntos más importantes que necesitas para poder programar plugins con modelos, vistas, controladores y tareas rake.

Además, hay muchas otras charlas que prometen ser interesantes. Para los que no os podais pasar, colgaré en este blog el material que use para mi ponencia y, si todo va bien, habrá streaming de video en vivo y se subirán las grabaciones a la web oficial (aunque como hay que editar el video, eso seguro que lleva unos meses).

searchwords: rails plugins, conferencia rails 2007

Publicado en conferenciarails, conferenciarails2007, conferencias, desarrollo, javier ramirez, ruby on rails | Sin Comentarios »

RadRails 0.9.1

Publicado por javier ramirez en Octubre 27, 2007

Después de que la anterior beta de RadRails funcionase solamente para eclipse 3.2, finalmente hay disponible una nueva beta, la 0.9.1, que puede correr en Eclipse Europa (he probado en 3.3 y todo funciona bien, aunque no sé si en la 3.4 se comportará igual).

La url para el update manager de eclipse es http://update.aptana.com/update/rails/beta/3.2

Si todavía no usas ningún IDE para tu desarrollo con Ruby o Rails, te recomiendo que le eches un vistazo. Aunque es cierto que Eclipse es algo pesado, en un ordenador moderno no debería tener mucho problema para ejecutarse de forma fluída. El conjunto de aplicaciones mínimo que ejecuto a la vez en mi máquina cuando desarrollo es un Eclipse 3.3 con RadRails, una o dos instancias de Mysql, FireFox, Thunderbird, Pidgin, Winamp, Notepad++, Console2, Kerio PF y AVG. Además, es muy habitual que tenga de fondo Emule o Skype, algún documento de OpenOffice y un Internet Explorer para ir probando. Y por supuesto todo el resto de servicios normales que corren normalmente en un XP.

Con esa configuración y con 2 megas gigas de RAM en un portátil normal comprado en el MediaMarkt hace más de un año, no noto ningún problema cuando trabajo con RadRails. Muy de vez en cuando, en algún caso raro de autocompletado se me queda pensando medio minuto, pero no es lo normal. En mi máquina anterior, un portátil con 4 años de antigüedad y 1 año giga de RAM, RadRails era usable pero de vez en cuando me hacía esperar más de la cuenta.

Hay otros IDEs y seguro que todos tienen sus puntos fuertes y sus puntos débiles. De momento no he visto ninguno que tenga nada tan espectacular como para hacerme plantearme un cambio. Mis motivos para escoger Eclipse son principalmente que lo conozco desde hace años como IDE para desarrollo en Java y me siento cómodo con él, que tiene una cantidad desorbitante de plugins para casi cualquier cosa, que es open source y multiplataforma, y que es un entorno que soporta muy bien el desarrollo en prácticamente cualquier lenguaje de programación. Profesionalmente lo he usado para desarrollar/editar Java, JavaScript, ASP, HTML, CSS, PHP, C++, y Ruby.

Entre mis características favoritas de Eclipse con RadRails están la navegación entre diferentes clases con un click, la búsqueda de clases y recursos, la integración con subversion y con la base de datos, la depuración gráfica, la gestión de los servidores Rails, la refactorización de código y vistas, y la asistencia al programar Ruby, HTML, CSS, o JavaScript.

Aparte de eso hay muchos detalles que hacen el día a día del desarrollo mucho más cómodo que usar un editor plano y la línea de comandos, a la que cada día recurro menos.

Bueno, llegados a este punto y como acabo de entregar el cuarto capítulo de una serie de nueve, ya es prudente anunciar que desde hace unos meses ando metido en la creación de un libro sobre RadRails.

A raíz de una conversación en la lista rubyonrails-talk me surgió la oportunidad de escribirlo y a pesar de que inicialmente no estaba muy seguro de querer dedicar el tiempo libre que me queda a esa tarea, acabó pudiéndome la curiosidad. Si todo va bien, terminaré de escribirlo para principios de 2008.

El título bajo el que previsiblemente se publicará es “RoR Made Easy with Aptana Radrails” y la editorial que anda detrás de esto es Packt Publishing

searchwords: RadRails, Aptana, Eclipse, PacktPublishing, javier ramirez, book

Publicado en desarrollo, javier ramirez, radrails, ruby on rails | 2 Comentarios »

conferencia rails en versión original (castellano sin subtítulos)

Publicado por javier ramirez en Septiembre 29, 2007

La conferencia rails europea ya ha terminado… los videos están en internet… los contenidos son muy interesantes, pero… tienen chistes de chiquito? NOOOORL!!!

Tras el éxito de la convocatoria del año pasado y animados por la acogida de la comunidad, la conferencia rails de habla hispana arranca de nuevo. Las fechas para esta edición son el 22 y 23 de noviembre.

Dos días de comunidad, conferencias, libros a buen precio y networking. Además, es el único día del año en que puedes llevarte tu portátil a una cena y no ser “#{you.is_female? ? ‘La rarita’ : ‘ El rarito’} del grupo!”.

El año pasado hubo lleno, así que no esperes mucho para registrarte en el sitio de la conferencia.

Y si te gusta el diseño, me ha contado un pajarito que se va a montar un concurso para el diseño de las camisetas, así que no pierdas de vista el feed del blog, donde se irá dando toda la información relevante.

Por cierto, si quieres dar una charla, todavía estás a tiempo. Puedes ver las propuestas que ya hemos recibido para no repetirte, y algunos temas propuestos de los que desde la organización creemos que estaría bien tener alguna conferencia.

searchwords: conferencia rails 2007

Publicado en conferenciarails, conferenciarails2007, javier ramirez, ruby on rails | Sin Comentarios »

usando method_missing y alias_method_chain

Publicado por javier ramirez en Septiembre 16, 2007

En este post voy a comentar cómo usar algunas de las características que más me gustan de Ruby y Rails: la posibilidad de reabrir una clase en cualquier momento, poder capturar las llamadas a métodos que no existen en un objeto, y la posibilidad de hacer alias de métodos (y encadenarlos)

Para ilustrar todo esto y ver qué podemos hacer, vamos a modificar el comportamiento de la clase Hash de forma que pueda hacer lo siguiente


>> me={:name=>’javier’}
=> {:name=>”javier”}
>> me.name
=> “javier”
>> me.last_name
NoMethodError: undefined method `last_name’ for {:name=>”javier”}:Hash
from (irb):18:in `method_missing’
from (irb):33
from :0

Si intento hacer eso sobre cualquier Hash, me devolvería un error directamente en la línea donde hago “me.name”, ya que la forma correcta de acceder a los elementos de una hash es mediante el operador []. La forma de acceder al campo “name” sobre una Hash cualquiera sería “me[:name]“. Con las modificaciones que vamos a realizar, conseguiremos un uso un poquito más conciso (a la manera que tiene ActiveRecord con los atributos de nuestro modelo).

Añadir el método ‘name’ a mi Hash sería muy simple. Aprovechándonos de que Ruby me permite reabrir una clase en cualquier momento, podría hacer simplemente esto


class Hash
  def name
    self[:name]
  end
end

Esto sería perfecto, pero implica que conocemos previamente el nombre de los campos a los que queremos acceder y además necesitamos escribir un método por campo. No parece una buena opción. Si conocemos previamente el nombre de los campos podríamos usar Struct y olvidarnos.

Entonces, si no sabemos previamente el nombre de los campos, ¿cómo sabemos qué métodos implementar? La respuesta es simple: no lo sabemos y no lo podemos saber. Pero… y ¿qué hacemos entonces?

Aquí es donde entra en juego una de las características que más me gustan de Ruby. Cuando un objeto recibe un mensaje que no entiende, Ruby automáticamente invoca a un método especial del Kernel. Este método es method_missing. Nota: ‘mensaje’ es el nombre que se usa en teoría de objetos cuando hablamos de un método. Realmente lo que tenemos son objetos que se envían mensajes entre ellos.

El método method_missing es un método del Kernel, pero si yo reabro una clase y defino el método, cuando se invoque a method_missing para esa clase conseguiré interceptar todas las llamadas a métodos no existentes. El intérprete de ruby nos va a pasar dos parámetros, el primero es el nombre del método, y el segundo son los parámetros que se usaban en la invocación, si los había.

Ahora ya podríamos hacer lo siguiente


class Hash
  def method_missing(method_name,*args)
    self[method_name]  if self.member?(method_name)
  end
end

Y esto ya casi hace lo que queremos, pero hay todavía un pequeño detalle. Si pedimos un campo que no existe, vamos a obtener un nil en lugar de una excepción. Esto no tiene porqué ser malo, y de hecho podría ser el comportamiento deseado. Pero no es lo que planteábamos originalmente. Queremos que si el campo existe nos lo devuelva, y si no existe se comporte como antes de sobreescribir el método.

Para poder hacer este tipo de cosas en Ruby, usamos la posibilidad de hacer alias de los métodos. La forma habitual es hacer un alias del método original con un nombre tal que loquesea_old y después desde el método nuevo que escribimos podemos invocar al antiguo mediante el alias definido. Esto tiene un problema inherente a la propia arquitectura de una aplicación en Ruby. Como las clases por definición se pueden reabrir en cualquier momento, cualquiera puede redefinir un método en cualquier momento, con lo que corremos el riesgo de estar ocultando un método sobreescrito previamente al hacer un alias.

Para evitar este tipo de problemas, en el código interno de rails se usa un patrón que funciona bastante bien. Cuando se define un nuevo método que va a ocultar a uno viejo al que se hará alias, se usa un sufijo para indicar qué tipo de funcionalidad implementa. Después se definen los alias de esta forma


alias :method_missing_without_access_by_key, :method_missing
alias :method_missing, :method_missing_with_access_by_key

A la hora de definir nuestro método nuevo, lo definiremos con el patrón nombre_antiguo_with_sufijo_indicando_funcionalidad. En nuestro caso se definiría como “method_missing_with_access_by_key”. De esta forma, aunque varios plug-ins diferentes intenten hacer alias de un mismo método, mientras no colisione el sufijo con uno que ya existe no tendremos problemas, con lo que se reduce el riesgo de tener conflictos de nombres.

Como este patrón es muy interesante, desde la versión 1.2 está implementado como parte del core de rails, bajo el nombre “alias_method_chain”. Podemos hacer simplemente


alias_method_chain :method_missing, :access_by_key

Esto busca un método que se llame method_missing_with_access_by_key y aplica los dos alias que hemos visto antes.

Así que la versión final de nuestro pequeño hack quedaría del siguiente modo


class Hash
  def method_missing_with_access_by_key(method_name,*args)
  self.member?(method_name) ? self[method_name] : method_missing_without_access_by_key(method_name,*args)
end

alias_method_chain :method_missing, :access_by_key
end

Todavía hay espacio para hacer alguna pequeña mejora, que probablemente explicaré en un post más adelante.

searchwords: method_missing, alias_method_chain, ruby alias method, Struct

Publicado en desarrollo, javier ramirez, ruby, ruby on rails | Sin Comentarios »

nuevo proyecto en rails: www.mirubi.com

Publicado por javier ramirez en Septiembre 7, 2007

Durante los últimos dos/tres meses he dedicado gran parte de mi tiempo (junto a otras personas del equipo) a desarrollar la web mirubi.com. A pesar de estar en fase Beta está teniendo una acogida bastante interesante y nuestro cliente ya está lanzando versiones en Reino Unido, Alemania, Francia y USA.

Como todos los desarrollos que hacemos en ASPgems es una solución 100% Rails. La aplicación es multi-país, multi-idioma y multi-marca, permitiendo a los partners una personalización de la apariencia.

Para gestionar la complejidad del deployment de los diferentes países a sus entornos de pruebas y producción hemos usado Capistrano 2.0 con tareas personalizadas.

La escalabilidad ha sido una de nuestras preocupaciones en este proyecto, y hemos hecho un uso intensivo de memcached tanto para almacenar consultas como fragmentos de html donde ha sido posible. El resultado está siendo muy satisfactorio, y hasta ahora los picos que ha habido ni se han hecho notar en el rendimiento.

La verdad es que es uno de esos proyectos donde hay mucho más trabajo en todas las tareas que corren por detrás que en la interfaz del usuario en sí misma y nos ha valido para poner a prueba varias cosas. Con cada desarrollo que entregamos me voy afianzando más en la idea de que hoy por hoy para el desarrollo de una aplicación web dinámica (independientemente del tamaño), la mejor opción es Ruby on Rails.

searchwords: rails, mirubi, capistrano, memcached, aspgems, sites

Publicado en javier ramirez, ruby on rails, sites | Sin Comentarios »

Seleccionar elementos de un Array de forma aleatoria

Publicado por javier ramirez en Septiembre 4, 2007

A veces viene bien poder mostrar el contenido de un Array de forma aleatoria en Ruby. Por ejemplo, puedes querer mostrar en una tagcloud los tags más populares pero no quieres mostrarlos en orden para que quede más estético.

Normalmente usamos el método sort_by en arrays compuestos de objetos complejos para compararlos por algún campo, por ejemplo para un resultado de una consulta de AR podríamos hacer:

my_array.sort_by{|x| x.amount}

Podemos utilizar el mismo método de una forma simple para “desordenar” cualquier Array:

my_array.sort_by{rand}

Y con esto tendremos un array desordenado “al azar”. Podríamos incluso abrir la clase Array y definir un método shuffle que hiciera justamente esto, tal que así

  class Array
    def shuffle
      self.sort_by{rand}
    end
  end

Y ahora ya podemos hacer:

my_array.shuffle

searchwords: ruby, array, sort_by, shuffle

Publicado en desarrollo, javier ramirez, ruby, ruby on rails | Sin Comentarios »

includes anidados / encadenados en rails (eager loading)

Publicado por javier ramirez en Diciembre 10, 2006

Ya sabemos que mediante el uso de Associations podemos conseguir eliminar el problema de las n+1 selects cuando queremos cargar datos de una tabla y su tabla asociada. Esto es lo que se conoce como eager loading.

Siguiendo la documentación, está claro que se puede hacer include de n tablas de golpe haciendo :include =>[tabla1,tabla2], y obtendremos datos tanto de nuestra tabla original como de las tablas tabla1 y tabla2. Un punto a tener en cuenta es que el tipo de joins que se hacen son LEFT OUTER, por lo que obtendremos todos los registros de la tabla original y solamente los que tengan datos de las tablas relacionadas.

Hasta aquí, todo perfecto cuando quieres hacer una select con tablas que están relacionadas con tu modelo directamente; pero si quieres hacer de una tacada una query que incluya las tablas relacionadas y a su vez las tablas relacionadas de éstas, no parece que sea posible. No al menos mirando solamente la documentación.

Sin embargo, una de las cosas interesantes del open source es que le podemos echar un vistazo al código fuente y ver qué es lo que hace exactamente, teniendo de esta forma la mejor documentación posible.

Tras una investigación alrededor de ActiveRecord(*ver más abajo), encontramos que, cuando se definen asociaciones, a la hora de montar la query se diferencia entre tres casos diferentes: si la asociación es un Symbol/String, si es un Array o si es una Hash. Aquí es donde está la gracia. En la documentación sólo nos explican el caso de Symbol/String y de Array, pero… y si le paso una Hash?.

Si le paso una Hash, consigo justamente lo que quería, poder incluir en la query las tablas relacionadas y las relacionadas con ellas. La sintáxis ,no tan obvia, para esto es la siguiente:

:include=>[{:tabla1=>[:tabla1_A,:tabla1_B]}]

Esto me carga las relaciones de mi modelo con tabla1, y a su vez las de tabla1 con tabla1_A y con tabla1_B, ahorrándonos bastante carga contra la base de datos.

* A continuación muestro el extracto de la clase JoinDependency, definida en Associations.rb donde se lleva a cabo la magia de las asociaciones

def construct(parent, associations, joins, row)
  case associations
  when Symbol, String
    while (join = joins.shift).reflection.name.to_s != associations.to_s
    raise ConfigurationError, “Not Enough Associations” if joins.empty?
    end
    construct_association(parent, join, row)
  when Array
    associations.each do |association|
    construct(parent, association, joins, row)
    end
  when Hash
    associations.keys.sort{|a,b|a.to_sb.to_s}.each do |name|
    association = construct_association(parent, joins.shift, row)
    construct(association, associations[name], joins, row) if association
    end
  else
    raise ConfigurationError, associations.inspect
  end
end



def construct_association(record, join, row)
  case join.reflection.macro
  when :has_many, :has_and_belongs_to_many
    collection = record.send(join.reflection.name)
    collection.loaded
    return nil if record.id.to_s != join.parent.record_id(row).to_s or row[join.aliased_primary_key].nil?
    association = join.instantiate(row)
    collection.target.push(association) unless collection.target.include?(association)
  when :has_one, :belongs_to
    return if record.id.to_s != join.parent.record_id(row).to_s or row[join.aliased_primary_key].nil?
    association = join.instantiate(row)
    record.send(”set_#{join.reflection.name}_target”, association)
  else
    raise ConfigurationError, “unknown macro: #{join.reflection.macro}”
  end
  return association
end

searchwords: include, nested include, chained include, eager loading, associations, JoinDependency

Publicado en desarrollo, javier ramirez, ruby on rails | Sin Comentarios »