Publicidad:
La Coctelera

RoR-Lab

Evolución, anécdotas, problemas y soluciones durante el desarrollo de una aplicación web con Ruby on Rails

22 Marzo 2007

¿Como poner código rjs en una vista?

Hola de vuelta.
Resulta que durante el desarrollo necesité crear la siguiente funcionalidad:
"Cuando el usuario haga click en un link, se debe desplegar los detalles de información de ese link. En los detalles debe aparecer un link "cancelar" que esconda nuevamente los detalles."
La idea era realizar algo similar a la creación cuando se utiliza AjaxScaffold.

La primera parte se realizó utilizando una llamada Ajax que obtenía los detalles del link presionado.
Para la segunda parte "esconder nuevamente el contenido", me molestó mucho tener que escribir nuevamente un archivo rjs, lo que implicaba realizar un nuevo llamado Ajax desde el navegador hasta el servidor para una tarea que no lo necesitaba.

Buscando un poco en internet encontré lo siguiente que fue genial!.

 <!-- Parametros: nc (una nueva_calificacion) -->
 Email: <%= nc.email %> <br/>
 Nombre: <%= nc.nombre %> <br/>
 Fecha: <%= nc.fecha_creacion %> <br/>
 Calificacion: <%= nc.valor %> <br/>
 Comentario: <%= nc.comentario.contenido %><br/>
 <br/>
 <%= link_to_function('Cancelar', update_page do |page|
     page.visual_effect(:blind_up, "nc_detalle_#{nc.id}")
  end) -%>
 

Saludos!

Tags: tips

servido por Luis Felipe sin comentarios compártelo

22 Marzo 2007

Clase para generar aleatorios

En mi última entrada en este blog, mostré el método que permitía generar una llave aleatoria.
Las cosas han ido evolucionando y resultó que uno de los formularios del sistema requería el famoso CAPTCHA que igualmente debía generar 4 caracteres aleatorios.
RoR fomenta fuertemente el principio DRY (Don't Repeat Yourself). Y bueno, en cualquier otro lenguaje es mejor no repetir código.
De manera que escribí una clase que generara aleatorios. Esta clase es como una especie de utilidad, por lo tanto debe ir dentro del directorio lib ; allí cree un directorio utilidades y dentro de este la clase GeneradorAleatorios; acá les presento el código para que me den sus opiniones:

class Utilidades::GeneradorAleatorio

CHARS = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
NUMBERS = ("0".."9").to_a

# genera una palabra aleatoria con la cantidad de caracteres especificada
# utiliza las letras de la 'a' a la 'z' minúsculas y masyúsculas y los números del '0' al '9'
def self.generar_palabra(cantidad = 10)
return self.generar(cantidad) { CHARS }
end

# genera una número aleatorio con la cantidad de dígitos especificada
# utiliza los números del '0' al '9'
def self.generar_numero(cantidad = 10)
return self.generar(cantidad) { NUMBERS }
end

# genera una cadena de caracteres aleatoria
# debe proveerse un bloque que retorne un arreglo de donde se sacarán los caracteres
def self.generar(cantidad = 10)
if block_given?
caracteres = yield
else
caracteres = CHARS
end
aleatorio = ""
1.upto(cantidad) { |i| aleatorio << caracteres[rand(caracteres.size)] }
return aleatorio
end
end

Así mas o menos se debería usar:

  • Generar un String de 4 caracteres de un arreglo específico.

Utilidades::GeneradorAleatorio.generar(4) { ['1','0','a','b','z'] }

  • Generar un String de 40 caracteres, letras mayúculas, minúsculas y digitos:

Utilidades::GeneradorAleatorio.generar_palabra(40)

  • Generar un String de 30 caracteres, pero solamente dígitos:

Utilidades::GeneradorAleatorio.generar_numero(30)

Saludos!

servido por Luis Felipe sin comentarios compártelo

22 Marzo 2007

Interceptar eventos en los modelos

¿Qué son los Callback?
Un callback es un método que se invoca automáticamente al realizarse alguna acción CRUD sobre un modelo (es decir, su clase es ActiveRecord).
Llevándolo a un plano de programación en base de datos, un callback vendría siendo lo que se conoce como un trigger.

Necesidad
Muy temprano en el desarrollo de la aplicación de la que trata este blog, necesité que antes de guardar un objeto en persistencia un atributo de dicho objeto quedara con un llave aleatoria de 50 caracteres.
La necesidad de esto es que luego debía enviar un email donde aparecía un link al sistema que realizaría un tarea fundamental de confirmar la nueva calificación.
Enviar el link con el id del objeto no era una opción porque al ser secuencial, fácilmente un bot podía confirmar todas las nuevas calificaciones!

Implementación
Me remití entonces a escribir un método dentro del modelo NuevaCalificacion, que generara la llave aleatoria...

# genera una llave aleatoria de 50 caracteres para utilizar en la confirmación
# esta llave se utiliza para evitar poner al público el id de la nueva calificación
def generar_llave_confirmacion
caracteres = ("a".."z").to_a + ("A".."Z").to_a + ("0".."9").to_a
llave_aleatoria = ""
1.upto(50) { |i| llave_aleatoria << caracteres[rand(caracteres.size)] }
return llave_aleatoria
end

Luego de este método, cree un método que asigna realmente la llave aleatoria generada al atributo llave_confirmacion ...

# pone los datos por defecto
def poner_datos_defecto
self.fecha_creacion = Time.now

# asegura que se genere una llave de confirmación que no exista (muy baja probabilidad, pero Murphy existe)
begin
llave = generar_llave_confirmacion
end while NuevaCalificacion.find_by_llave_confirmacion(llave)

self.llave_confirmacion = generar_llave_confirmacion
end

En realidad, el método poner_datos_defecto, no se encarga solamente de dar una llave aleatoría a nuestra nueva calificación, sino que también pone la fecha en otro atributo.
Poner la fecha me gustó mas así, que utilizar la características automática de Rails porque queda implícito para un futuro desarrollador y no tengo que dejar un objeto con referencias en inglés y otras en castellano.

Finalmente debe indicársele al modelo que el método poner_datos_defecto, es un callback que debe ser invocado justo antes de guardar una nueva calificación.

class NuevaCalificacion < ActiveRecord::Base

# ... codigo

before_save :poner_datos_defecto

# .. codigo (incluidos métodos poner_datos_defecto y generar_llave_confirmacion
end

Eso fue todo...
Así cada vez que se invoca el método save en un objeto cuya clase es NuevaCalificacion, aseguramos que fecha_creacion y llave_confirmacion, referencien automáticamente objetos por defecto.

Saludos!

servido por Luis Felipe sin comentarios compártelo

22 Marzo 2007

Poniendo todo en UTF-8

Leyendo un poco, me encuentro con que en RoR (y pensándolo mejor en cualquier otro framework) es mejor tenerlo todo con la misma configuración para el manejo de caracteres, especialmente si nuestra aplicación no está escrita en inglés.
Estas son algunas especificaciones del ambiente donde desarrollo la aplicación:

  1. Sistema Operativo: Windows XP (SP2)
  2. Base de datos: MySQL 4.1
  3. Ruby versión 1.8.4
  4. Rails versión 1.2.1
  5. RadRails como IDE de desarrollo (recomendada!)

Base de datos a UTF-8
Entonces hay que comenzar diciéndole a MySQL que maneje los caracteres en UTF-8. Luego de navegar un poco encuentro la forma y realmente funciona. En el directorio de instalación de MySQL, en el archivo my.ini, buscar la sección [mysqld] y ahí poner la configuración. Este es un pedazo de mi archivo, luego de configurarlo:

...

# CLIENT SECTION
# ----------------------------------------------------------------------
#
# The following options will be read by MySQL client applications.
# Note that only client applications shipped by MySQL are guaranteed
# to read this section. If you want your own MySQL client program to
# honor these values, you need to specify it as an option during the
# MySQL client library initialization.
#
[client]

port=3306

[mysql]

default-character-set=utf8

# SERVER SECTION
# ----------------------------------------------------------------------
#
# The following options will be read by the MySQL Server. Make sure that
# you have installed the server correctly (see above) so it reads this
# file.
#
[mysqld]

# The TCP/IP Port the MySQL Server will listen on
port=3306

#Path to installation directory. All paths are usually resolved relative to this.
basedir="C:/Archivos de programa/MySQL/MySQL Server 4.1/"

#Path to the database root
datadir="C:/Archivos de programa/MySQL/MySQL Server 4.1/Data/"

# The default character set that will be used when a new schema or table is
# created and no character set is defined
character-set-server=utf8
collation-server=utf8_spanish_ci
default-character-set=utf8
default-collation=utf8_spanish_ci

...


Decirle a Rails que la base de datos está en UTF-8
Luego hay que decirle a Rails que nuestra base de datos está en UTF-8, para esto editamos el archivo config/database.yml ; en mi caso la conexión a la base de datos de desarrollo, quedó así:

development:
adapter: mysql
database: soyconsumidor_development
username: sc
password: sc
host: localhost
encoding: utf8

IDE en UTF-8
Luego seguí con mi IDE de desarrollo que es RadRails. Esto si que fue fácil:

  1. Iniciar RadRails.
  2. Ir a Window / Preferences ... ; ahí se despliega un ventana de configuración.
  3. En el árbol de la izquierdad seleccionar: General / Workspace
  4. Buscar el panel con el título "Text file enconding"; ahí seleccionar la opción "Other" y luego de la lista desplegable seleccionar "UTF-8".
  5. OK.


Diciéndole a RoR que trabaje en UTF-8
También hay que habilitar RoR para que entienda que todo se va a manejar con UTF-8. Esto se hace en el archivo config/enviroment.rb ; poniéndole al final la siguiente instrucción:

$KCODE = 'u'

Como se está utilizando Rails 1.2.1, este no debe ser necesario ya que por defecto viene con $KCODE en UTF-8.

Enviando el HTML en UTF-8
Finalmente le puse una funcionalidad a la aplicación para que todo el contenido que se responda a los clientes vaya codificado (como no!) en UTF-8. Para lo anterior cree un filtro para que indique en los headers (los que no se ven) de las respuestas enviadas a los navegadores, cual es la codificación de caracteres que estoy utilizando. El filtro es un método en la clase ApplicationController que está escrita en app/controllers/application.rb :

# Filters added to this controller will be run for all controllers in the application.
# Likewise, all the methods added will be available for all controllers.
class ApplicationController < ActionController::Base

# filtros antes de enviarse la respuesta al browser
after_filter :set_content_type

# filtro para poner la codificaciones de caracters a UTF-8
def set_content_type
headers["Content-Type"] ||= "text/html; charset=utf-8"
end
end

En Rails 1.2
el Content-Type ya viene por defecto en UTF-8, así que tampoco debería ser obligatorio este paso.

Es bueno también poner en el tag <head> de los html construidos esta misma directiva.
Algo así como:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

</head>

Eso es todo...
Espero sus comentarios!

Agradecimientos a Xavier Noria por sus comentarios!

servido por Luis Felipe sin comentarios compártelo

22 Marzo 2007

Configurar pluralización para castellano

Gracias a juanma por enviar la configuración la pluralización de RoR para castellano. Hoy mismo voy a probarla, me tomará un poco pero seguro aparecerán en este blog los resultados. Esta es la configuración que debe ir en el archivo [directorio aplicación]/config/environment.rb. La he modificado un poco para que se ajuste a las necesidades de la aplicación:

Inflector.inflections do |inflect|
inflect.plural %r{$}, 'es'
inflect.plural %r{s$}, 's'
inflect.plural %r{z$}i, 'ces'
inflect.plural %r{([aeiou])$}i, '\1s'
# inflect.plural %r{_(.*)$}, 's_\1'

inflect.singular %r{s$}i, ''
inflect.singular %r{es$}i, ''
inflect.singular %r{ces$}i, 'z'
inflect.singular %r{des$}i, 'd'
inflect.singular %r{res$}i, 'r'
# inflect.singular %r{(.*)s_(.*)}i, '\1_\2'

inflect.irregular 'nueva_calificacion', 'nuevas_calificaciones'

#inflect.uncountable %w( palabra_igual_plural_que_singular )
end


Enlaces

  1. El siguiente enlace habla un poco mas sobre la pluralización (muestra la misma configuración enviada por juanma: http://www.shinkitune.com/blogonrails/2006/03/10/10-consejos-para-principiantes-en-rails/
  2. Definición de la palabra inflexión, según la real academia de la lengua.

servido por Luis Felipe sin comentarios compártelo

22 Marzo 2007

Iteración 1: Los modelos

Ya con los Story Cards se definió una primera iteración del desarrollo que consistía en crear los modelos. Los modelos en el sistema son objetos ORM (Object Relational Mapping), pero que también manejan mucha lógica del negocio. Ellos son:

  1. Calificación: representa una calificación realizada por una persona.
  2. Comentario: es el texto relacionado a una calificación, se creó como un modelo aparte porque los textos pueden llegar a ser muy largos y leerlos siempre desde persistencia sería ineficiente.
  3. Consumidor: persona que utiliza el sistema.
  4. Empresa: quien provee los productos a ser calificados.
  5. Industria: agrupa las empresas de acuerdo a su actividad; es decir, de acuerdo al tipo de productos que provee.
  6. Calificación Nueva: representa una calificación hecha por un consumidor pero que aún no ha sido publicada para búsquedas.
  7. Producto.
  8. Rechazo: calificación que fue rechazada por los operadores del sitio debido a que su comentario no es apropiado para publicarse.
  9. Referido: persona que recibe una invitación a utilizar el sistema gracias a que fue referenciado por un consumidor registrado.
  10. Usuario: persona que debe autenticarse en el sistema para realizar tareas administrativas o de operación. Acá estarían por ejemplo los operadores del sitio, el administrador, etc.

Tags: diseno

servido por Luis Felipe sin comentarios compártelo

22 Marzo 2007

Story Cards

  1. El sistema permite que a través de Internet las personas puedan calificar positiva o negativamente productos de consumo (servicios también). Además, las personas pueden ver las calificaciones realizadas por otros para un producto en específico.
  2. El sistema debe tener un módulo para los operadores del sistema quienes filtran las calificaciones para evitar publicar aquellas que tienen contenido no apropiado.
  3. Cuando una persona realiza una calificación selecciona el producto, realiza un comentario, provee su nombre y su correo electrónico, y específica si la calificación es positiva o negativa. El sistema envía un correo electrónico a la persona con un enlace para que ésta pueda confirmar su calificación; asegurando así que las personas provean correos electrónicos válidos. Luego de confirmada, la calificación es revisada por los operadores del sistema quienes determinan si es apta para publicarse o debe ser rechazada. El sistema en ambos casos envía otro correo electrónico a la persona informándole que sucedió con su calificación.
  4. La información sobre las calificaciones es pública y puede ser consultada por cualquier persona quien debe previamente seleccionar el producto específico que desea revisar.
  5. El sistema proveerá un mecanismo de referidos donde las personas que ya tengan calificaciones publicadas, puedan registrar correos de otras personas quienes recibirán un email invitándolas a visitar el sistema y calificar en el mismo. Esta funcionalidad permitirá realizar campañas de premios para incentivar las visitas en el sitio.
Tags: analisis

servido por Luis Felipe sin comentarios compártelo

22 Marzo 2007

Desarrollo Ágil



En este blog publico los avances del desarrollo de una aplicación web
desarrollada con Ruby on Rails (RoR).

Como RoR está enfocado al desarrollo ágil, me dispuse y comencé a leer sobre XP (eXtreme Programming), SCRUM, "Manifesto for Agile Software Development", etc. Un muy buen sitio al rededor del cual viven estas metodologías es Agile Alliance.

Como soy principiante en estos temas, decidí tomar lo que a mi criterio era mas útil para el desarrollo de este proyecto.

Comencé entonces y escribí lo que se llaman Story Cards (Tarjetas de Historias), donde se plasma textualmente lo que el cliente cuenta sobre como debe funcionar el sistema. Estos Story Cards me parece que son mas útiles cuando se hacen de manera muy global (mirando el proyecto desde 5 kilómetros de distancia) para luego ir acercándose y especificando cada vez mas.

Tags: analisis

servido por Luis Felipe sin comentarios compártelo


Sobre mí

Actualmente me encuentro desarrollando una aplicación web que espero tener en producción para la mitad del 2007. La aplicación está desarrollada utilizando el framework Ruby on Rails. (RoR) Toda la evolución del sistema va a ser documentada en este blog con el ánimo de recibir retroalimentación o bien ser útil para otros desarrollos.

Fotos

Luis Felipe Hurtado Campuzano todavía no ha subido ninguna foto.

¡Anímale a hacerlo!

Buscar

suscríbete

Selecciona el agregador que utilices para suscribirte a este blog (también puedes obtener la URL de los feeds):

¿Qué es esto?

Crea tu blog gratis en La Coctelera