La mitad de las veces que busco en google información sobre ruby busco las mismas cosas, las que soy incapaz de memorizar dado mi estado neuronal. Una de ellas es ésta: el formateo de Time, Date y DateTime.
Los que más uso, extaído del link...
%d - Day of the month (01..31)
%H - Hour of the day, 24-hour clock (00..23)
%m - Month of the year (01..12)
%M - Minute of the hour (00..59)
%S - Second of the minute (00..60)
%w - Day of the week (Sunday is 0, 0..6)
%y - Year without a century (00..99)
%Y - Year with century
Por cierto, te has apuntado ya a la conferencia Rails de Madrid?
martes, 16 de octubre de 2007
domingo, 14 de octubre de 2007
Firewatir sobre Windows
Después de darme de cabezazos contra un servidor y no poder terminar un crawler ni con rest-open-uri ni con mechanize, he terminado por programarlo sobre firewatir.
El punto de mayor información sobre fire watir es éste.
Y después de instalar la extensión de Firefox, instalar la gema FireWatir, lo y arrancar firefox con firefox.exe -jssh el código es muy sencillo:
require 'firewatir'
include FireWatir
#me hago con un navegador
my_firefox = Firefox.new
#voy a la página que me interesa
my_firefox.goto('http://www.danimata.com')
#relleno un combo
my_firefox.select_list(:name, 'Genre').select_value('man')
#relleno un campo de texto
my_firefox.text_field(:name, 'FirstName').set('Daniel')
#pincho el botón que submite la página
my_firefox.button(:value, "Continue").click
Así de fácil es y así se lo hemos contado. Como siempre, salud¡
El punto de mayor información sobre fire watir es éste.
Y después de instalar la extensión de Firefox, instalar la gema FireWatir, lo y arrancar firefox con firefox.exe -jssh el código es muy sencillo:
require 'firewatir'
include FireWatir
#me hago con un navegador
my_firefox = Firefox.new
#voy a la página que me interesa
my_firefox.goto('http://www.danimata.com')
#relleno un combo
my_firefox.select_list(:name, 'Genre').select_value('man')
#relleno un campo de texto
my_firefox.text_field(:name, 'FirstName').set('Daniel')
#pincho el botón que submite la página
my_firefox.button(:value, "Continue").click
Así de fácil es y así se lo hemos contado. Como siempre, salud¡
jueves, 4 de octubre de 2007
SOAP hasta en la SOPA
Madre del amor¡
Llevo tres días intentando desentrañar cómo acceder a un Web Service que no tiene descubrimiento por wsdl. Lo único que tenía era unos xsd medio decentes (y digo medio decentes porque xsd2ruby cascaba al ejecutarlo contra ellos) y unos fuentes java que se supone que funcionan. Además, el acceso se realiza sin SOAP action.
Después de intentar emular al script wsdl2ruby y generar los objetos y métodos que él genera con estas manitas y mi tricotosa he tenido que generar un mensaje con su SOAPHeader y su SOAPBody y enviarlo por el método invoke de SOAP::RPC::Driver. Entre todas las pruebas que he tenido que hacer destaco estas tres:
driver = SOAP::RPC::Driver.new("http://localhost:8003", "http://my.namespaces")
sh = SOAP::SOAPHeader.new
sb = SOAP::SOAPBody.new
sb.add('Message', SOAP::SOAPElement.new('Message'))
sb[0].extraattr['xmlns'] = 'http://my.namespaces'
sb[0].extraattr['xmlns:xsi'] = 'http://www.w3.org/2001/XMLSchema-instance'
sb[0].extraattr['xsi:schemaLocation'] = 'http://my.schemas'
sb[0].add(SOAP::SOAPElement.new('Header'))
sb[0].add(SOAP::SOAPElement.new('Body'))
sb[0]['Header'].add(SOAP::SOAPElement.new('MessageID', "000000")) sb[0]['Body'].add(SOAP::SOAPElement.new('Operation'))
sb[0]['Body']['Operation'].add(SOAP::SOAPElement.new('Query', 'This is my query'))
sb[0]['Body']['Operation'].extraattr['OperationName'] = 'QueryRequest'
sb[0]['Body']['Operation'].extraattr['OperationType'] = 'My type'
...
@resp = driver.invoke(sh, sb)
...
code = @resp[1]['Message']['Body']['Operation']['Responses'] ['Response']['Reference']['Code'].data
0.upto((@resp[1]['Message']['Body']['Operation']['Responses'] ['Response']['Records'].members.size rescue 0) - 1) do |r|
puts @resp[1]['Message']['Body']['Operation']['Responses'] ['Response']['Records'][r]['Id'].data
end
Salud¡
Llevo tres días intentando desentrañar cómo acceder a un Web Service que no tiene descubrimiento por wsdl. Lo único que tenía era unos xsd medio decentes (y digo medio decentes porque xsd2ruby cascaba al ejecutarlo contra ellos) y unos fuentes java que se supone que funcionan. Además, el acceso se realiza sin SOAP action.
Después de intentar emular al script wsdl2ruby y generar los objetos y métodos que él genera con estas manitas y mi tricotosa he tenido que generar un mensaje con su SOAPHeader y su SOAPBody y enviarlo por el método invoke de SOAP::RPC::Driver. Entre todas las pruebas que he tenido que hacer destaco estas tres:
- después de observar un mensaje recibido como error del servidor de destino, vi que su SOAPBody contenía objetos SOAPStruct e intenté emularlo para crear la estructura XML que el servidor entiende.
- tuve que cambiar todos los SOAPStruct por SOAPElement porque el servidor aplicaba sus xsd al contenido recibido y los nodos enviados llevaban el atributo encodingstyle, no aceptado en el formato esperado.
- cada SOAPElement se puede tratar como Hash y cada SOAPStruct como Hash y como Array.
driver = SOAP::RPC::Driver.new("http://localhost:8003", "http://my.namespaces")
sh = SOAP::SOAPHeader.new
sb = SOAP::SOAPBody.new
sb.add('Message', SOAP::SOAPElement.new('Message'))
sb[0].extraattr['xmlns'] = 'http://my.namespaces'
sb[0].extraattr['xmlns:xsi'] = 'http://www.w3.org/2001/XMLSchema-instance'
sb[0].extraattr['xsi:schemaLocation'] = 'http://my.schemas'
sb[0].add(SOAP::SOAPElement.new('Header'))
sb[0].add(SOAP::SOAPElement.new('Body'))
sb[0]['Header'].add(SOAP::SOAPElement.new('MessageID', "000000")) sb[0]['Body'].add(SOAP::SOAPElement.new('Operation'))
sb[0]['Body']['Operation'].add(SOAP::SOAPElement.new('Query', 'This is my query'))
sb[0]['Body']['Operation'].extraattr['OperationName'] = 'QueryRequest'
sb[0]['Body']['Operation'].extraattr['OperationType'] = 'My type'
...
@resp = driver.invoke(sh, sb)
...
code = @resp[1]['Message']['Body']['Operation']['Responses'] ['Response']['Reference']['Code'].data
0.upto((@resp[1]['Message']['Body']['Operation']['Responses'] ['Response']['Records'].members.size rescue 0) - 1) do |r|
puts @resp[1]['Message']['Body']['Operation']['Responses'] ['Response']['Records'][r]['Id'].data
end
Salud¡
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¡
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¡
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¡
Suscribirse a:
Entradas (Atom)