viernes, 14 de septiembre de 2007

Memory leaks re-revisited

De nuevo, mejorando lo que hay.

La extensión de Time mucho mejor así:

class Time
  def method_missing(method_name, *args)
    cadena = self.strftime('%Y/%m/%d')
    return cadena.send(method_name, *args)
  end
end


Gracias Javi por tu ayuda.

Salud¡

Memory leaks revisited

Qué hay de nuevo?

He tenido que apretar un tornillo que se había quedado suelto con el tema del cambio en el acceso a sqlserver. Ocurre que, con ADO.rb, los datos de tipo datetime eran devueltos como Time si se obtienen a través de un modelo o como String si se obtienen mediante una query directa a la base de datos. Con ODBC siempre son devueltos como Time.

Por ello he tenido que extender el objeto Time para que no casquen los accesos con [], por ejemplo, en los casos en los que ADO.rb retornaba String.

En environment.rb (o mejor en algún fichero incluido en éste):

class Time
  def [](range = nil)
    return self.strftime('%Y/%m/%d')
  end
end

Salud¡

jueves, 13 de septiembre de 2007

Memory leaks conectando a sqlserver

Danimata al aparato.

Llevo N días viendo cómo una de nuestras aplicaciones, que trabaja contra sqlserver, padece de alzehimer, quicir, pierde memoria con cada petición.

Mi conexión era la siguiente:

adapter: sqlserver
database: dddddd
username: uuuuuu
password: xxxxxx
host: hhhhhh

Mi amigo Xavi me ha pasado un par de links en el que esto mismo le ocurre aquí y allá a otras personas que trabajan contra sqlserver a través de ADO.rb de la librería ruby-dbi. Recomiendan pasarse a ODBC.

He creado el origen de datos y mi conexión ha quedado como sigue:

adapter: sqlserver
database: dddddd
username: uuuuuu
password: xxxxxx
host: DBI:ADO:Provider=SQLOLEDB;Data Source=midatasource;

Lo he hecho, y nada de nada, el alzehimer continúa. Claro que no me había deshecho totalmente de ADO.rb. De nuevo Xavi con la solución. Con lo que me queda la siguiente conexión:

adapter: sqlserver
mode: odbc
dsn: my_dsn
database: dddddd
username: uuuuuu
password: xxxxxx

Et voilá¡ Todo funcionanado sin pérdidas de memoria y con la sensación de que las conexiones funcionan mejor y más rápido.

Como siempre, salud¡

martes, 28 de agosto de 2007

Dime con quién andas y te diré que RESCUE necesitas

Últimamente estoy decubriendo el uso de rescue y creo que estoy enamorado. Estamos acostumbrados a picar conociendo al dedillo lo que puede ocurrir y lo que no en la ejecución de nuestros programas y eventualmente dejamos de lado el control de errores. rescue no sólo ayuda en esta tarea sino que además se integra camaleónicamente el código de forma que apenas impacta en el mismo.

I love rescue.

viernes, 17 de agosto de 2007

Link interesante

Madre del amor que abandonado tengo esto.

El día 29 nació mi 'segundo proyecto a largo plazo'. Se llama Samuel y es tan bueno como su hermano Hugo.

A lo que iba: mi amigo Diego me ha pasado este link con un minitutorial de ActiveRecord bastante completo.

Tengo pendiente comentar el manejo de documentos Word y Excel. No se me ha olvidado pero me faltan manos y horas.

Como siempre, salud¡

jueves, 19 de julio de 2007

Una red social y una aplicación de facturación

Mi amigo Xavi Noria está a punto de terminar facturagem, la nueva ASP que ASPgems pone a disposición de autónomos, pymes y medianas empresas para la gestión de sus facturas.

Por otra parte, hemos participado en el desarrollo de dialogo, una red social 100% española que está pegando fuerte.

Como siempre, salud¡

miércoles, 13 de junio de 2007

win32ole + openoffice

Recientemente he tenido que construir un proceso ruby que fuese capaz de tratar documentos hechos con ms-word. Para ello, se puede encontrar información en este blog. En un próximo comentario haré un resumen de lo básico en tratamiento de documentos ms-word y hojas de cáculo ms-excel con la librería win32ole.

Sin embargo, como paso intermedio, estuve buscando información acerca de cómo tratar documentos de ms-word a través de openoffice y utilizando también la librería antesmencionada. Poca encontré, la verdad, pero un poco de aquí unido a la información que obtuve del blog que he recomendado y listo.

Una vez hecho

require 'win32ole'

estamos en disposición de crear un 'manejador' de openoffice de la siguiente manera:

serviceManager = WIN32OLE.new("com.sun.star.ServiceManager")

Lo siguiente es abrir el escritorio de openoffice

desktop = serviceManager.createInstance("com.sun.star.frame.Desktop")

con lo que ya estamos listos para abrir documentos, editarlos y guardarlos igual que si trabajásemos directamente con la aplicación.

Podemos abrir un documento de la siguiente manera:

document = desktop.loadComponentFromURL('file:///c:/IRPHsin.doc', '_blank', 0, [])

y salvarlo con un nuevo nombre:

document.storeAsURL('file:///c:/IRPHsin2.doc', [])

Se puede manejar fácilmente su título

document.title = "Nuevo título"

o el nombre del fichero...

document.filename = "nombre.doc"

para luego guardarlo...

document.save

o acceder a su texto a través de...

document.text

Como esto ya está muy pesado, seguiremos depués de la publicidad.

Salud¡

miércoles, 25 de abril de 2007

Controlando el ratón

Hoy he necesitado tener controlado el punto exacto en el que se encontraba el ratón al pinchar sobre los links y botones de mi aplicación. Mirando aquí y allá lo he conseguido con el siguiente código javascript:

clickY = 0;
offsetY = 0;
clickIE = document.all ? true : false;
if (!clickIE) document.captureEvents(Event.MOUSEDOWN);
document.onmousedown = md;
function md(e){
 if (clickIE) {
  if (document.documentElement && document.documentElement.scrollTop){
   offsetY = document.documentElement.scrollTop;
  }
  else{
   offsetY = document.body.scrollTop;
  }
  clickY = event.clientY + offsetY;
 }
 else {
  clickY = e.pageY;
  if (self.pageYOffset){
   offsetY = self.pageYOffset;
  }
 }
 if (clickY < 0){clickY = 0;}
 return true;
}


Con ello tenemos controlados en todo momento dos valores muy interesantes para abrir popups o menús de tipo drop down hechos con capas:

clickY, el punto en el eje Y del navegador donde se ha hecho click con el ratón
offsetY, el punto en el eje Y del navegador hasta donde se ha hecho scroll


Que aporveche¡

miércoles, 18 de abril de 2007

Envío de mails

Aunque esta información está en muchos sitios, la voy a escribir para no tener que mirarala en ningún sitio e ir a tiro hecho.

Para enviar mails desde una aplicación rails, hay que seguir los siguientes pasos:

1 - Fichero de configuración

Hay que crear el archivo mailer.rb en el directorio config de la aplicación. Éste contiene la configuración del sevidor de mail que vamos a utilizar. Por ejemplo:

ActionMailer::Base.delivery_method = :smtp
ActionMailer::Base.default_charset = "utf-8"
ActionMailer::Base.server_settings = {
:address => "smtp.danimata.com",
:port => 25,
:domain => 'www.danimata.com',
:user_name => "si1329@danimata.com",
:password => "aikman11",
:authentication => :login
}

2 - Controlador

En el controlador, por ejemplo form_controller.rb, crearemos tantas acciones como consideremos necesarias. Se puede utilizar una única acción para enviar todos los mails en función de los datos recibidos o bien una por cada tipo de mail que necesitemos. Lo importante es que en estas acciones es donde se harán las comprobaciones pertienetes y se llamará a los métodos del nuestro modelo mailer.

3 - Modelo

Debe de heredar de ActionMailer::Base. Tendrá un método mail_tipo_de_mail(parametros) por cada tipo de mail a enviar. En ellos se asigna valor a las variables globales que se utilizan para el envío. Por ejemplo:

def mail_new_password(user, new_passwd)
@subject = 'Nuevo password para AutoGassi'
@recipients = user.email
@from = MAIL_FROM
@sent_on = Time.now
@headers = {}

@charset = 'utf-8'
@content_type = "text/html"

@body["email"] = user.email
@body["first_name"] = user.first_name
@body["last_name"] = user.last_name
@body["passwd"] = new_passwd
end

4 - Vista

Por cada método del modelo, existirá una vista del mismo nombre. En ellas se formatea la información como se considere oportuno. Resulta muy fácil hacerlo como HTML. Por ejemplo, mail_new_password.rhtml

<!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" lang="en" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>AutoGassi</title>
</head>
<body>
Estimad@ <%= h(@first_name) %> <%= h(@last_name) %>,

<br/>Ésta es tu nueva contraseña de acceso a la web danimata.com:

<br/>Nuevo password: <%=@passwd%>

<br/>Puedes cambiarla una vez hayas entrado en la aplicación.
</body>
</html>

Para información más detallada, consultar rubyonrails.org.

Salud.

viernes, 30 de marzo de 2007

Manejo de fechas vacías con dynarch_calendar

En la aplicación en la que estoy trabajando necesito poder manejar fechas vacías con dynarch_calendar y no encuentro cómo hacerlo utilizando los métodos y parámetro existentes. He tenido que meter un par de cambios en el código del bundle que paso a enumerar:

- dynarch_calendar.rb

La última línea del método dynarch_date_select queda como

buffer << "<script>convert_date_container_to_dynarch_calendar('#{object_name}', '#{method_name}', #{index}, '#{object.send(method_name) ? initial_date : ''}', '#{object.send(method_name) ? initial_display : ''}', '#{image_url}')</script>\n"

de forma que si el campo fecha está vacío pase los parámetros initial_date e initial_display en vacío.

- convert_calendar_field.js

Cuando llega vacío y se utiliza en la línea 22

date = Date.parseDate(initial_date, ifFormat);

genera un objeto Date con la fecha del día. Por ello hay que trucar la asignación de los campos hidden en las líneas 28-30 de la siguiente manera:

dynarch_contents += "<input type='hidden' " + name_and_id('1i', 'year') + " value='" + (initial_date != '' ? date.getFullYear() : '') + "'>\n";
dynarch_contents += "<input type='hidden' " + name_and_id('2i', 'month') + " value='" + (initial_date != '' ? (date.getMonth() + 1) : '') + "'>\n";
dynarch_contents += "<input type='hidden' " + name_and_id('3i', 'day') + " value='" + (initial_date != '' ? date.getDate() : '') + "'>\n";


- Mi formulario

La línea que genera el calendario en mi formulario queda de la siguiente manera:

<%= dynarch_date_select 'vehicle', 'garage_out_date', {:date_format => "%d/%m/%Y", :use_month_names => spanish_month_names, :include_blank => true} %>

donde

def spanish_month_names
return ['Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre']
end

con lo que conseguimos que si no hay javascript habilitado, los combos que se generan se vean en castellano y con una opción en blanco para poder dejar la fecha vacía.