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¡
viernes, 14 de septiembre de 2007
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¡
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¡
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.
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¡
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¡
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¡
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¡
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.
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.
- 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.
Suscribirse a:
Entradas (Atom)