Howto/tutorial

Como crear un archivo zip con ruby

Hace unos días me encontré con el problema de generar archivos Zip que contuvieran archivos de un curso de SCORM, ¿Cómo hacerlo?, lo primero que me vino a la mente fue Ruby!!!

La gema que me sirvió para esto fue rubyzip, y con el siguiente fragmento de código se realizaron los archivos zip:

Espero que les sirva como a mi.

Links:

http://ruby-doc.org/core/classes/Dir.html
http://ruby-doc.org/core/classes/FileUtils.html
http://rubyzip.sourceforge.net/

Enviando correo de manera asíncrona en Rails usando Workling, Workling-Mailer y RabbitMQ

Enviando correo de manera asíncrona en Rails usando Workling, Workling-Mailer y RabbitMQ (English)

El trabajar con message queues es bastante interesante, ya que podemos mandar procesos al background y que estos sean procesados de manera asíncrona, un ejemplo podría ser el envío de correos, aunque también podría servir para realizar otras tareas, por ejemplo, como el envío de mensajes sms, generación de reportes, generación de pdf’s, etc.

En esta ocasión les quiero presentar como enviar correos de manera asíncrona haciendo una aplicación sencilla haciendo uso de los puglins Workling y workling-mailer y del sistema RabbitMQ, en teoría, con esto se podría ajustar esta solución fácilmente a cualquier otro proceso que se quiera realizar de manera asíncrona.

Aplicación base

Se crea una aplicación básica con restful_authentication, y con la opción de activación.

Lo primero que hacemos es crear la aplicación en rails

rails mail_async_example -d mysql
 
rm public/index.html
 
script/plugin install git://github.com/technoweenie/restful-authentication.git
 
script/generate authenticated user sessions --include-activation

Creamos nuestra base de datos y migramos

rake db:create
 
rake db:migrate

Y hacemos unos pequeños cambios al código de la aplicación para enviar correo según las instrucciones de restful_authentication, así que agregamos lo suguiente:

config/routes.rb

map.activate 'activate/:activation_code', :controller => 'users', :action => 'activate', :activation_code => nil

config/environment.rb

config.active_record.observers = :user_observer

Con esto ya tendríamos nuestra aplicación básica la cuál podríamos probar de inmediato apuntando en el browser a http://localhost:3000/signup

Y agregando algunas cosillas extras, a app/controller/application_controller.rb agregamos la línea:

include AuthenticatedSystem

Esta misma línea que agregamos al Application controller la removemos de app/controller/sessions_controller.rb y de app/controllers/users_controller.rb

Y creamos un nuevo controlador

script/generate controller portal index

Modificamos config/routes.rb para agregar al último como página root

map.root :controller => "portal"

Por último agregamos un layout para nuestra aplicación:

app/views/layouts/application.html.erb

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
  <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
  <title>Contracts: <%= controller.action_name %></title>
  <%= stylesheet_link_tag 'scaffold' %>
</head>
<body>
<% if current_user %>
   <%= link_to 'Logout', logout_path %>
<% else %>
   <%= link_to 'Login', login_path %>
   <%= link_to 'Sign up', signup_path %>
<% end %>
 
<% [:error, :warning, :notice].each do |level|
    if flash[level] -%>
      <div class="flash <%= level.to_s -%>"><%= flash[level] -%></div>
  <% end -%>
<% end -%>
 
<%= yield %>
 
</body>
</html>

Instalando amqp, workling y workling_mailer

Ahora bien, antes de instalar Workling, para poder trabajar con RabbitMQ es necesario instalar la gema de amqp, esta gema requiere también de la gema de EventMachine, por lo que al instalar amqp también instalará EventMachine.

gem sources -a http://gems.github.com/
sudo gem install tmm1-amqp --no-rdoc --no-ri

Vemos nuestro listado de gemas

sudo gem list

Ahora si, a instalar workling y workling_mailer

script/plugin install git://github.com/purzelrakete/workling.git
 
script/plugin install git://github.com/langalex/workling_mailer.git

Para poder utilizar workling con RabbitMQ agregamos al final de config/environment.rb

config.after_initialize do
Workling::Remote.invoker = Workling::Remote::Invokers::EventmachineSubscriber
Workling::Remote.dispatcher = Workling::Remote::Runners::ClientRunner.new
Workling::Remote.dispatcher.client = Workling::Clients::AmqpClient.new
end

Posteriormente en app/models/user_mailer.rb añadimos

include AsynchMail

A la fecha de hoy el plugin de workling tiene un pequeño issue, para resolverlo hacemos lo siguiente en el archivo lib/workling/clients/memcache_queue_client.rb y verificar que contiene:

require 'memcache'

Al principio del archivo, si no lo tienes agrégalo.

Como el amqp corre sobre un ciclo de EventMachine es necesario correr nuestra aplicación con Thin, ya que este servidor soporta EventMachine sin ningún problema. Para instalar Thin corremos

sudo gem install thin --no-rdoc --no-ri

Instalando RabbitMQ

Checar la instalación aquí http://www.jcastaneyra.com/2009/06/07/instalando-rabbitmq/

A correr todos

Nos aseguramos de que el RabbitMQ esté corriendo.

Iniciamos el cliente de workling

script/workling_client start

E iniciamos el servidor thin

thin start

Apuntamos nuestro browser a http://localhost:3000 y nos registramos con un usuario, al verificar el log de desarrollo veremos que el correo ahora es enviado después de todas las últimas operaciones registradas en el log. Podemos probar quitando la línea de include AsynchMail del UserMailer y ver lo que hace, o bien haciendo nuevo proceso que sea pesado y que se realice en background.

Referencias:

http://github.com/christospappas/workling/commit/063b9849b32e0c6140a5ecdb254357770d9bd28f
http://github.com/purzelrakete/workling/
http://github.com/langalex/workling_mailer/
http://github.com/tmm1/amqp/
http://github.com/technoweenie/restful-authentication/
http://www.rabbitmq.com
http://code.macournoyer.com/thin/
http://www.jcastaneyra.com/2009/06/07/instalando-rabbitmq/

Sending mails in asynchronous way in Rails using Workling, Workling-Mailer and RabbitMQ (Español)

Working with message queues is so interesting, since we can put processes in the background in order to be processed in asynchronous way, imagine this to send several mails, or maybe for heavy tasks as sms messages, report generation, pdf generation, etc.

So, with this post I want you to show how to send mails in asynchronous way, we are going to make a small application using Workling, Workling-mailer and as message queue RabbitMQ, actually we could adjust this solution to any other problem with async process requirement.

Base application

We create a simple application with restful_authentication and activation option.

First of all we create the rails app

rails mail_async_example -d mysql
 
rm public/index.html
 
script/plugin install git://github.com/technoweenie/restful-authentication.git
 
script/generate authenticated user sessions --include-activation

Now with rake we create and migrate DB

rake db:create
 
rake db:migrate

Following the restful_authentication instructions to send mail we add this:

config/routes.rb

map.activate 'activate/:activation_code', :controller => 'users', :action => 'activate', :activation_code => nil

config/environment.rb

config.active_record.observers = :user_observer

Our base app is working now, so to test it we get the url http://localhost:3000/signup in the browser.

Add this in app/controller/application_controller.rb:

include AuthenticatedSystem

The same line added to Application controller is removed from app/controller/sessions_controller.rb and app/controllers/users_controller.rb

We create a new controller for portal index

script/generate controller portal index

And modify config/routes.rb to add portal as root

map.root :controller => "portal"

And last we create a layout for our application:

app/views/layouts/application.html.erb

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
  <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
  <title>Contracts: <%= controller.action_name %></title>
  <%= stylesheet_link_tag 'scaffold' %>
</head>
<body>
<% if current_user %>
   <%= link_to 'Logout', logout_path %>
<% else %>
   <%= link_to 'Login', login_path %>
   <%= link_to 'Sign up', signup_path %>
<% end %>
 
<% [:error, :warning, :notice].each do |level|
    if flash[level] -%>
      <div class="flash <%= level.to_s -%>"><%= flash[level] -%></div>
  <% end -%>
<% end -%>
 
<%= yield %>
 
</body>
</html>

Installing amqp, workling and workling_mailer

Now, before using Workling, we need RabbitMQ and amqp is needed, this gem also requires EventMachine gem, so, both gems are installed when amqp is installed.

gem sources -a http://gems.github.com/
sudo gem install tmm1-amqp --no-rdoc --no-ri

List your installed gems

sudo gem list

Now, install workling and workling_mailer

script/plugin install git://github.com/purzelrakete/workling.git
 
script/plugin install git://github.com/langalex/workling_mailer.git

Add this to config/environment.rb to allow workling to use RabbitMQ

config.after_initialize do
Workling::Remote.invoker = Workling::Remote::Invokers::EventmachineSubscriber
Workling::Remote.dispatcher = Workling::Remote::Runners::ClientRunner.new
Workling::Remote.dispatcher.client = Workling::Clients::AmqpClient.new
end

To app/models/user_mailer.rb add this

include AsynchMail

Until today I’ve seen a little issue with workling, to solve it we do the folloging in this file lib/workling/clients/memcache_queue_client.rb; verify that you have:

require 'memcache'

Add it if you don’t have it.

Amqp runs in an EventMachine cycle, so it is needed to run our app with Thin, since Thin supports EventMachine without any problem. To install Thin run

sudo gem install thin --no-rdoc --no-ri

Installing RabbitMQ

Follow the instructions here http://www.jcastaneyra.com/2009/06/07/instalando-rabbitmq/

Everybody runs

Cool, naw we ensure that RabbitMQ is running.

Start workling client

script/workling_client start

And start Thin server

thin start

Point with your browser to http://localhost:3000 and sign up a new user, then verify your log and will see that email is sent and registered to the end of log after all operations. We can test removing include AsynchMail from UserMailer and see what happens, it would be great if you test some application with a heavy process working in the background.

Links:

http://github.com/christospappas/workling/commit/063b9849b32e0c6140a5ecdb254357770d9bd28f
http://github.com/purzelrakete/workling/
http://github.com/langalex/workling_mailer/
http://github.com/tmm1/amqp/
http://github.com/technoweenie/restful-authentication/
http://www.rabbitmq.com
http://code.macournoyer.com/thin/
http://www.jcastaneyra.com/2009/06/07/instalando-rabbitmq/

Como obtener una imagen ISO de un CD/DVD en Mac

Hace poco un compañerito de la comunidad de México on Rails mencionó que tener una Mac es como tener lo mejor de ambos mundos (de Windows y Linux), y he aquí el porqué, resulta que quería obtener una imagen ISO de cierto DVD para respaldarlo y posiblemente después quemarlo, y aquí les muestro al más puro estilo Unix como se puede hacer.

Primero que nada hay que insertar el CD/DVD a extraer (duh! pero alguien podría no saber :) )

Y ejecutando el siguiente comando obtenemos el status del CD/DVD a quemar:

jcastaneyra$ drutil status
Vendor   Product           Rev
OPTIARC  DVD RW AD-5630A   1CHQ
 
Type: DVD-ROM              Name: /dev/disk1
Sessions: 1                  Tracks: 1
Overwritable:   00:00:00         blocks:        0 /   0.00MB /   0.00MiB
Space Free:   00:00:00         blocks:        0 /   0.00MB /   0.00MiB
Space Used:  330:41:69         blocks:  1488144 /   3.05GB /   2.84GiB
Writability:
Book Type: DVD-ROM (v1)

Posteriormente desmontamos el CD/DVD:

jcastaneyra$ diskutil unmountDisk /dev/disk1
Unmount of all volumes on disk1 was successful

Y ahora obtenemos la imagen con la utilidad dd:

jcastaneyra$ dd if=/dev/disk1 of=vista.iso bs=2048
1488144+0 records in
1488144+0 records out
3047718912 bytes transferred in 1209.311307 secs (2520210 bytes/sec)

Después para expulsar el CD/DVD lo que se hace es volverlo a montar (jejeje, talvez puede haber otra forma, posiblemente haya un comando eject, ya no lo probé):

jcastaneyra$ diskutil mountDisk /dev/disk1
Volume(s) mounted successfully

Y por último probamos la imagen ISO:

jcastaneyra$ hdid vista.iso
/dev/disk2                                                 /Volumes/VISTA_32_BUSINESS

Y para poder quemar la imagen ISO se podría utilizar la aplicación “Utilidad de Discos”

Problemas de memoria en mi 256slice

No se si ya había comentado, pero mi blog lo tengo en un VPS de slicehost y tengo una 256slice es decir una partición virtual con 256 Mb de memoria, y recientemente debido al monto de memoria limitado (talvez debería pensar seriamente en subir el monto de memoria por unos cuántos dolares más al mes, ¿debería?) he experimentado algunos problemas ya que mi servidor se había estado muriendo, y en los logs estaba la evidencia:

Dec 15 08:27:59 ubuntu kernel:  [<ffffffff8025d987>] out_of_memory+0x2e/0x187

Por lo que me puse a investigar y encontré unos ajustes que se le tienen que hacer a la configuración del servidor apache2:

<IfModule mpm_prefork_module>
    StartServers          3
    MinSpareServers       3
    MaxSpareServers       3
    ServerLimit          50
    MaxClients           50
    MaxRequestsPerChild   1000
</IfModule>

Además, también instalé el plugin de wordpress WP Super cache para bajarle un poco al proceso de php con la base de datos.

Espero que esto funcione, estoy intentando esto antes de subir a 512 Mb de memoria, y digo ojalá que esta experiencia pueda ayudar a alguien más que se encuentre en un problema parecido.

Cómo dirigir el tráfico de mi viejo blog en wordpress a mi nuevo blog en mi propio dominio

Tiene rato ya que adquirí mi propio dominio y mi servicio de hosting para colocar mi blog, cuando esto sucedió resultó que tenía tráfico en el blog de mi dominio nuevo y también en el de mi blog viejito hospedado en wordpress.com, y resulta que con el tiempo mi blog viejito empezó a adquirir lectores, poquitos pero mucho más que el blog nuevo, esto es lógico después de casi dos años aumentó el tráfico. Cuando hice el cambio al nuevo blog me pregunté como podría hacerle para redirigir el tráfico de mi viejo blog (jcastaneyra.wordpress.com) a mi nuevo blog (www.jcastaneyra.com), recuerdo que me puse a buscar pero no encontré nada hasta hace apenas un par de días.

Hacer la redirección desde wordpress a un dominio en específico es algo truculento, pero gracias a BlogWell la tarea fue fácil ya que ellos lo explican claramente hasta con un documento pdf, para los que no se les dé mucho el inglés, aquí les dejo algo muy resumido de lo que hice.

1. Primero que nada, los url’s del viejo y nuevo blog deben coincidir (por eso también tengo wordpress en mi nuevo blog, al menos ahora).
2. Segundo, tratar de agregar en la administración del viejo blog (jcastaneyra.wordpress.com) en la parte de mejoras y dominios el nuevo dominio (www.jcastaneyra.com), esto marcará un error.


3. Para solucionar el error, es necesario cambiar los Domain Servers para el dominio a los servidores de wordpress (ns1.wordpress.com, ns2.wordpress.com, ns2.wordpress.com), en este caso el dominio nuevo (www.jcastaneyra.com) está con GoDaddy.com.


4. Una vez que se apunta a los servidores de wordpress con el nuevo dominio, se intenta agregar de nueva cuenta el dominio, para poder agregar dominios en wordpress.com es necesario tener 10 créditos, esto es igual a US$10, por lo que tuve que pagar con paypal. El dominio nuevo (www.jcastaneyra.com) es agregado y este apunta al viejo blog (jcastaneyra.wordpress.com).


5. Ahora, habrá que cambiar la redirección, para eso en la administración de wordpress, configurar al nuevo dominio (www.jcastaneyra.com) como dirección de blog dando click en  donde dice “Colocar la bitácora aquí”, con esto el viejo blog (jcastaneyra.wordpress.com) apuntará al nuevo blog (www.jcastaneyra.com).


6. Y por último regresar la configuración de Domain Servers que se tenían originalmente, mi dominio fue comprado con GoDaddy.com pero lo tengo administrado con Slicehost.com, por lo que mis servidores originales son (ns1.slicehost.net, ns2.slicehost.net, ns3.slicehost.net), ya después les platico de lo que hice para poner mi blog con Slicehost.com.


Y listo, con esto ya tengo redireccionado mi viejo blog a mi nuevo blog, jejeje el único problema que yo veo es el que tuve que pagar US$10 y lo peor es que el dolar ha subido a MXN $ 12, pero en fin, creo que vale la pena.

Como habilitar los gravatars en jaws

Pues bien, haciendo referencia a Jaws apenas en el post de “Cómo agregar videos de youtube en Jaws”, ahora traigo un nuevo post, en el que vamos a ver como habilitar la opción de ver los gravatars en los comentarios.

Pero, para empezar ¿Qué es un gravatar?, de la definición en site.gravatar.com:

What is a gravatar?

A gravatar, or globally recognized avatar, is quite simply an 80×80 pixel avatar image that follows you from weblog to weblog appearing beside your name when you comment on gravatar enabled sites. Avatars help identify your posts on web forums.

¿Y qué es un avatar?, de la definición de wikipedia.org:

An avatar (abbreviations include AV, ava, avie, avy, avi, avvie, avis, avies, avii, and avvy) is an Internet user’s representation of himself or herself, whether in the form of a three-dimensional model used in computer games, a two-dimensional icon (picture) used on Internet forums and other communities, or a text construct found on early systems such as MUDs. The term “avatar” can also refer to the personality connected with the screen name, or handle, of an Internet user.

Ahora bien, para poder usar un gravatar en Jaws, tenemos que crear nuestro gravatar en http://site.gravatar.com/, para esto tenemos que crear una cuenta que asocie la imagen que queremos usar como gravatar a nuestro correo electrónico, la creación del gravatar es bastante intuitiva.

Ya que hemos creado nuestro gravatar, ahora en los ajustes avanzados del panel de control de Jaws, habilitamos el uso de gravatars.

Cuando pongamos un comentario, al dejar nuestro correo electrónico que está asociado al gravatar, el comentario como tal ahora desplegará la imagen de nuestro gravatar.

Con esto ya podemos tener el gravatar habilitado en nuestro Jaws.

Cómo agregar videos de youtube en Jaws

Hace unos días me volví a meter, después de varios meses, a un servidor que tengo con unos amigos, el cuál tiene Jaws instalado, y pues le hice algo de mantenimiento, migré la versión que tenía 0.6.3 a 0.7.3, instalé algunos parches, le di algo de mantenimiento a la base de datos y saqué algunos respaldos.

Ya después, me puse a jugar un rato con mi nuevo Jaws y quise agregar un video de youtube, y me puse a buscar en la red, y busqué, y busqué … y no encontré nada (me pregunto que habrá pasado con la página de www.jaws-user.com), entonces me puse a probar y probar en la administración de jaws y haciendo posts de videos hasta que di con el problema y pude postear un video. Y ahora aquí quiero compartir como fue que se solucionó, es una solución sencilla, pero que me llevó un buen rato encontrarla.

El problema estaba en que en los ajustes avanzados del Panel de control tenía como editor el editor de tipo word/OpenWriter, pero este editor al querer agregar el código embebido de el video de youtube como que trunca el código.

La solución estuvo en cambiar este editor de tipo word/OpenWriter al editor clásico de Jaws, y con esto el código embebido de youtube no será truncado.

Ahora bien, cuando me refiero al código embebido del video de youtube, es al código que viene en la parte inferior a la etiqueta que dice Embed.

Y listo, con esto tendríamos un video de youtube en jaws ;)