Barcode4J en JRuby y Rails
Agosto 13th, 2010
En el post anterior había explicado el uso de Gbarcode, una librería para generación de códigos de barras con Ruby. El problema es que esta librería no se puede utilizar en Jruby ya que tiene extensiones nativas en C, cosa que Jruby aún no soporta.
Después de investigar alternativas de generación de codigos de barras para java como Zxing y Barbecue. Me quedé con Barcode4j por facilidad de implementación, documentación (la cual es muy completa) y sobre todo estabilidad.
A continuación paso a comentarles como utilizar esta librería en JRuby.
1) Lo primero es descargarse en paquete binario del sitio o bien de este enlace directo.
2) Al descomprimir el Zip, copiamos el contenido del directorio Build al directorio /lib de nuestra instalación de JRuby
3) Ahora vamos al código:
require 'java'
#Importamos algunas librerías que vamos a utilizar
import 'java.awt.image.BufferedImage'
import 'java.io.OutputStream'
import 'java.io.FileOutputStream'
#Importamos las librerías de los códigos de barras (Barcode4j) que necesitamos
import 'org.krysalis.barcode4j.impl.code39.Code39Bean'
import 'org.krysalis.barcode4j.impl.code128.Code128Bean'
import 'org.krysalis.barcode4j.impl.int2of5.Interleaved2Of5Bean'
import 'org.krysalis.barcode4j.impl.codabar.CodabarBean'
import 'org.krysalis.barcode4j.impl.code128.EAN128Bean'
import 'org.krysalis.barcode4j.impl.pdf417.PDF417Bean'
import 'org.krysalis.barcode4j.impl.upcean.EAN13Bean'
import 'org.krysalis.barcode4j.impl.upcean.EAN8Bean'
import 'org.krysalis.barcode4j.impl.upcean.UPCABean'
import 'org.krysalis.barcode4j.impl.datamatrix.DataMatrixBean'
import 'org.krysalis.barcode4j.output.bitmap.BitmapCanvasProvider'
import 'org.krysalis.barcode4j.tools.UnitConv'
#Creamos el Bean y establecemos los dpi y wide_factor
bean = Interleaved2Of5Bean.new()
dpi = 150
bean.wide_factor = 3
#Creamos la imagen
ofile = java.io.File.new('/home/laptop/barcodes/barcode.png')
out = FileOutputStream.new(ofile)
canvas = BitmapCanvasProvider.new(out,"image/x-png", dpi, BufferedImage::TYPE_BYTE_BINARY, false, 0)
#Generamos el código de barras
#El segundo parámetro que pasamos es el número del que deseamos generar el codigo de barras
bean.generate_barcode(canvas, '1234567890');
canvas.finish
out.close
Con esto, generamos una imagen con nuestro codigo de barras en /home/laptop/barcodes/barcode.png la cual se puede incluir en cualquier pdf/html/odf, etc.
Espero les sea útil. Cualquier duda, no duden en comentar.
Hay veces que el usuario necesita subir archivos, pero de una manera “masiva”, no guardando de a uno. Un claro ejemplo de esto es GoogleDocs,
que te deja subir varios documentos a la vez, antes de empezar a verlos.
Utilizando un plugin de jquery, en rails esto se hace de una manera muy transparente.
El plugin en cuestión se llama MultiFileUpload, en su página encontraremos una buena documentación de como usarlo correctamente
Lo que nos interesa es como implementarlo en rails y que todos estos archivos que seleccionamos se almacenen en nuestra base de datos.
Para comenzar tenemos que incluir las librerias del plugin en el aplication.html.erb
<% javascript_include_tag :default, 'multiple-file-upload/jquery.MultiFile.js', 'multiple-file-upload/jquery.MetaData.js' %>
En nuestra vista creamos el formulario, para subir los archivos
<% form_for(:archivo_digital, :html => {:multipart => true },:url => create_archivo_digital_path) do |f| %> <ul id="form"> <%= file_field_tag :files, :class => 'multi file', :name => 'pdf_files[]'%> <li> <%= f.submit 'Subir' %> <%= f.submit 'Cancelar' %> </li> </ul> <% end %>
Expliquemos un poco el código:
En necesario establecer :multipart => true, para que el formulario admita la carga de archivos.
file_field_tag nos crea el tag para poder abrir el cuadro de diálogo de carga de archivos de un navegador:
:class => ‘multi file’, esta clase es la que utiliza MultiFileUpload para hacer la magia de subir varios archivos
:name => ‘pdf_files[]‘ esto es muy necesario, porque el plugin crea un arreglo con todos los archivos, pero para que ruby sepa
que nos referimos a un arreglo tenemos que poner [].
Por último tenemos dos botones, el de Subir, que va a subir todos los archivos de una sola vez y el de Cancelar, que hará lo propio.
En nuestro controller vamos a tener
#Renderiza el formulario para subir los archivos def new @archivo_digital = ArchivoDigital.new respond_to do |format| format.html end end def create respond_to do |format| if params[:commit] == "Subir" unless params[:pdf_files].blank? params[:pdf_files].each do |archivo| params[:archivo_digital][:nombre_archivo] = archivo params[:archivo_digital][:archivo] = archivo.read @archivo_digital = ArchivoDigital.new(params[:archivo_digital]) if @archivo_digital.save flash[:notice] = 'Archivo agregado' end end format.html{redirect_to archivos_digitales_path} else flash[:error] = 'Debe seleccionar al menos un archivo' end else format.html{redirect_to archivos_digitales_path} end end end
Expliquemos un poco el código:
Sobre el primer método no hay mucho que decir, solo nos renderiza el formulario que creamos en el paso anterior
El método create es el que hace todo, para empezar tenemos una condición donde pregunta si params[:commit] == “Subir”
esto es para que diferencie entre el botón subir y el cancelar. Cuando presionamos un botón, rails inmediatamente manda un parámetro, llamado
commit con el nombre del botón. Con está condición lo que hacemos es darle tareas diferentes a cada botón.
Si no se cumple la condición, es porque se presionó el botón “Cancelar” y nos redirigirá al listado de archivos.
En caso de que la condición se cumpla, tenemos otro condicional: unless params[:pdf_files].blank?, esto es para saber si se seleccionó algun archivo_digital
y caso contrario muestra un flash[:error]. Si se cumple la condición, recorremos el arreglo y vamos guardando en nuestra base de datos el nombre del
archivo y el archivo en sí.
Bueno, esto es una manera sencilla de subir archivos de forma “masiva” con Jquery y Rails, cualquier cosa no duden en preguntar
JasperReports con Jruby y Rails
Julio 29th, 2010
Uno de los grandes problemas en el desarrollo con Ruby on Rails son los reportes multipágina. Debido a que el HTML (inclusive HTML 5) no soporta multipágina, si utilizamos Jruby tenemos la posibilidad de usar cualquier librería Java en nuestro desarrollo.
Afortunadamente en Java tenemos JasperReports (http://jasperforge.org/), una excelente solución al problema antes mencionado.
Para poder incluir un reporte realizado con JasperReports en nuestra aplicación Jruby necesitamos:
1) Descargar I-Report, la herramienta de administracion de reportes de JasperReports. http://jasperforge.org/projects/ireport y descomprimirlo.
2) Dentro del directorio del i-report, ir a modules/ext/ y copiar todos los archivos .jar (si, todos
) al directorio lib de la instalación de JRuby. De esta manera, ya incluimos las librerías necesarias y tenemos preparado nuestro JRuby para utilizar JasperReports.
3) Nos resta crear un reporte para prueba, si nunca hiciste un reporte con i-report: http://jasperforge.org//website/ireportwebsite/IR%20Website/ir_design_a_report.html?header=project&target=ireport
4) Finalmente el código para correr nuestro reporte es el siguiente:
require 'java'
import 'oracle.jdbc.OracleDriver' #Aqui necesitas Utilizar el Driver de la Base de datos que estas usando, en mi caso es oracle
import 'net.sf.jasperreports.engine.JasperCompileManager'
import 'org.apache.commons.dbcp.BasicDataSource'
import'java.util.HashMap'
import'net.sf.jasperreports.engine.JasperFillManager'
import'net.sf.jasperreports.engine.JasperExportManager'
#Creo el datasource
basicdatasource = BasicDataSource.new
basicdatasource.driver_class_name = 'oracle.jdbc.OracleDriver'
basicdatasource.username = 'usuario'
basicdatasource.password = 'password'
basicdatasource.url = 'jdbc:oracle:thin:@localhost:1521:XE'
basicdatasource.connection
conexion = basicdatasource.connection
#Compilamos el reporte
jasperReport = JasperCompileManager.compile_report('/url_de_tu_archivo_jrxml/reporte.jrxml')
#Para pasar los parámetros, definimos un objeto HashMap
m = HashMap.new
m.put('parametro_1','valor_parametro_1')
m.put('parametro_2','valor_parametro_2')
m.put('parametro_n','valor_parametro_n')
#Genero el reporte
jasperPrint = JasperFillManager.fill_report(jasperReport, m,conexion)
#Exporto el PDF
JasperExportManager.export_report_to_pdf_file(jasperprint, 'path_al_archivo_PDF.pdf')
Si deseamos generar reportes en Rails, podemos por ejemplo ubicar los reportes en el directorio public/reportes y utilizar send_file para enviarlos, por ejemplo:
JasperExportManager.export_report_to_pdf_file(jasperprint, RAILS_ROOT+"/public/reportes/reporte.pdf") send_file RAILS_ROOT+"/public/reportes/reporte.pdf"
Espero les sea de utilidad, cualquier cosa comenten y trataré de despejar dudas
Gbarcode. Codigos de barra con Ruby
Marzo 16th, 2010
Gbarcode es una librería de generación de códigos de barra para Ruby. Es una extensión de C que envuelve el proyecto GNU Barcode. Se distribuye en formato GEM
Link: http://gbarcode.rubyforge.org/
Ejemplo de uso:
require 'rubygems'
require 'gbarcode'
# Incluir el módulo
include Gbarcode
# Existen tres pasos para generar un codigo de barras
# 1) preparar el espacio para el string
# 2) codificar el string como un codigo de barras
# 3) imprimir el codigo de barras
# preparar el codigo de barras para el string "TEST1234"
bc = barcode_create("TEST1234")
# codificar el codigo de barras usando code 39,
# desde que code 39 no usa dígito de verificacion (checksum),
# lo podemos pasar en un flag
barcode_encode(bc, BARCODE_NO_CHECKSUM | BARCODE_39)
#imprimir el codigo de barras usando postcript
barcode_print(bc, File.new("testout.ps", "w"), BARCODE_OUT_PS)
# ó
barcode_print(bc, File.new("testout.eps", "w"), BARCODE_OUT_EPS)
Whenever: una manera sencilla de administrar tareas en Cron con Ruby
Marzo 15th, 2010
Si bien hace bastante tiempo que soy usuario de GNU/Linux, no suelo crear tareas en cron con frecuencia por lo que necesito investigar su poderosa sintáxis cada vez que debo crear trabajos que deben ejecutarse a intervalos regulares.
Hace poco por casualidad me topé con Whenever, una gema de Ruby que nos permite crear tareas en cron de manera muy sencilla. A través de un DSL nos abstrae de la complejidad de la sintáxis de cron. Whenever está muy integrado al framework de desarrollo web Ruby on Rails, aunque puede utilizarse en un programa independiente que genera salidas de tareas para cron y hasta actualiza el archivo crontab. En este post vamos a ver la manera de crear tareas con Whenever desde el punto de vista de un Administrador de Sistemas.
REST con Rails
Diciembre 29th, 2009
El uso de REST con Ruby on Rails es extremadamente relajante, una vez que comienzas a utilizar REST y te acostumbras a trabajar de esa forma, no quieres volver a la forma tradicional. Esta es una guía de conceptos básicos de REST y su aplicación en Rails.
REST son las siglas de Representational State Transfer (Transferencia de Estado Representacional), es una técnica de arquitectura software para sistemas hipermedia distribuidos como la World Wide Web. El término se originó en el año 2000, en una tesis doctoral sobre la web escrita por Roy Fielding, uno de los principales autores de la especificación del protocolo HTTP y ha pasado a ser ampliamente utilizado por la comunidad de desarrollo.
Tiempo transcurrido en letras en ruby on rails
Julio 27th, 2009
Muchas veces necesitamos calcular y mostrar en una forma legible el tiempo transcurrido desde una fecha hasta el día de hoy. Por ejemplo en twitter podemos ver el tiempo transcurrido de un tweet hasta el momento.
![]()
En Rails este proceso es muy sencillo utilizando el helper time_ago_in_words(), enviando como parámetro la fecha en la que ocurrió el evento. Es importante que el parámetro que le enviamos sea una fecha, en caso contrario nos dará una excepción de error de tipo de datos.
Por ejemplo si queremos saber cuanto tiempo pasó desde que se creó un ticket en nuestra base de datos, en la vista colocamos :
Esto nos dará un resultado como el ejemplo de la imagen, supongamos que pasaron 7 días:
# => 7 days
Hasta alli todo perfecto, pero que pasa si queremos nuestro resultado en castellano?, tenemos que redefinir en nuestro application_helper el método distance_of_time_in_words, simplemente copiamos y pegamos el siguiente código en nuestro application_helper.rb (o en cualquier helper, si solo lo queremos usar en un lugar específico)
def distance_of_time_in_words(from_time, to_time = 0, include_seconds = false)
from_time = from_time.to_time if from_time.respond_to?(:to_time)
to_time = to_time.to_time if to_time.respond_to?(:to_time)
distance_in_minutes = (((to_time - from_time).abs)/60).round
distance_in_seconds = ((to_time - from_time).abs).round
case distance_in_minutes
when 0..1
return (distance_in_minutes == 0) ? 'menos de um minuto' : '1 minuto' unless include_seconds
case distance_in_seconds
when 0..4 then 'menos de 5 segundos'
when 5..9 then 'menos de 10 segundos'
when 10..19 then 'menos de 20 segundos'
when 20..59 then 'menos de um minuto'
else '1 minuto'
end
when 2..44 then "#{distance_in_minutes} minutos"
when 45..89 then 'aproximadamente 1 hora'
when 90..1439 then "aproximadamente #{(distance_in_minutes.to_f / 60.0).round} horas"
when 1440..2879 then '1 dia'
when 2880..43199 then "#{(distance_in_minutes / 1440).round} dias"
when 43200..86399 then 'aproximadamente 1 mes'
when 86400..525959 then "#{(distance_in_minutes / 43200).round} meses"
when 525960..1051919 then 'aproximadamente 1 año'
else "mas de #{(distance_in_minutes / 525960).round} años"
end
end
Luego probamos nustra aplicación nuevamente y veremos que el resultado cambio a:
# => 7 dias
Rake doc, salvation
Junio 17th, 2009
A quién no le ha pasado que justo a la hora que necesitamos echar un vistazo a la documentación online de algún framework/lenguaje, nos encontramos con el gran problema que no tenemos conexión? Personalmente estoy tan (mal!) acostumbrado a ver la documentación online que muchas veces me he quedado sin avanzar culpa (mía primero) de la conexión.
Si estamos trabajando con rails, obtener la documentación de la api del framework es una cosa muy sencilla. En la consola nos situamos sobre el raiz de nuestra aplicación rails y ejecutamos:
carlos@gray-shadow:~/rails_apps/ciclope$ rake rails:freeze:gems
Esta tarea copia todos los gems (inclusive rails) en el directorio /vendor de nuestra aplicación, para que la aplicación en la que estamos ejecute los gems y rails en la versión “freezada”, el siguiente paso:
carlos@gray-shadow:~/rails_apps/ciclope$ rake doc:rails
Aqui Rake nos crea toda la documentación del api del framework tal cual lo tienes online (si! en formato html!). Solo debes ir al directorio doc/api (en el raiz de tu aplicación) y alli abrir con tu browser favorito el archivo “index.html”
Recuerda que tu aplicación ha quedado freezada, por lo que si instalas nuevos gems en el rails de tu sistema, no seran accesibles desde esta aplicación, pero no te asustes
para deshacer el freeze solo debes ejecutar:
carlos@gray-shadow:~/rails_apps/ciclope$ rake rails:unfreeze
Y ya tienes el api completo de rails en doc/api. Facil no? Y sobre todo muy útil
Pasando numeros a letras en Ruby on Rails
Diciembre 11th, 2008
Post movido a: http://www.ipcorp.com.ar/cbarbiero?p=11
Manipulando HTML y XML con Ruby y Hpricot
Diciembre 11th, 2008
Uno de los problemas que tenemos cuando usamos aplicaciones web es que al mandar un comando HTTP al servidor a través del navegador, el servidor convierte los datos con los que debemos trabajar en gran cantidad de código HTML. Si necesitamos que nuestro programa pueda trabajar con esos resultados es necesario “desconvertir” el HTML en los tipos de datos que queremos como arrays, strings y otros objetos.
En este tutorial vamos a construir un script en Ruby que nos permita utlizar las sugerencias que nos da el buscador de Google cuando cree que escribimos mal lo que buscamos, el popular “Quizás quiso decir”, gracias a una librería poderosa, rápida y fácil de usar: Hpricot para la tarea de parsear HTML, todo esto utilizando una metodología de desarrollo evolutiva.
Por estos lugares ruby no es aún un lenguaje muy popular, asi que primero les voy a explicar como tener todo lo necesario como para empezar a trabajar.
Estas instrucciones son para Ubuntu Linux pero pueden adaptarse para cualquier otra distribucion, y en MS Windows debería ser aún mas fácil.
Primero vamos a instalar los paquetes de desarrollo y compiladores básicos en Linux, más el interprete de Ruby y sus librerias de desarrollo
sudo aptitude install build-essential ruby ruby1.8-dev irb rdoc
Una vez que terminamos, seguimos con el gestor de paquetes de Ruby: RubyGems
wget http://rubyforge.org/frs/download.php/38646/rubygems-1.2.0.tgz tar -xvf rubygems-1.2-0.tgz cd rubygems-1.2-0.tgz sudo ruby setup.rb
Por ultimo instalamos el parseador de html Hpricot
sudo gem install hpricot
Ahora si, esta todo listo y podemos empezar con el desarrollo, de nuestro simple corrector ortográfico basado en google. Creamos un nuevo archivo ud_quiso_decir.rb en donde vamos a obtener el codigo fuente de un sitio y mostrarlo en pantalla, y a partir de aca vamos a hacer evolucionar el script
#importamos las librerias necesarias require 'open-uri' #abrimos la pagina deseada y mostramos su contenido por pantalla puts open('http://www.google.com.ar').read
Guardamos y ejecutamos.
ruby ud_quiso_decir.rb
Si todo salió bien en la pantalla debería aparecer un monton de código html, el siguiente paso es abrir esa url con Hpricot para poder manipular el código fuente.
#importamos las librerias necesarias require 'open-uri' require 'rubygems' require 'hpricot' #definimos en una variable la url url = 'http://www.google.com.ar' #creamos un objeto hpricot a partir de la url doc = Hpricot(open(url)) #mostramos el contenido limpio de tags html por pantalla puts doc.to_plain_text
Ahora tenemos que revisar el código que devuelve google cuando tipeamos mal una palabra, para eso en el sitio de google buscamos algo incorrecto como hinteligencia, revisando el código vamos a encontrar que lo que buscamos:
<span style="color: #cc0000">Quizás quiso decir: </span> <a href="/search?hl=es&sa=X&oi=spell&resnum=0&ct=result&cd=1&q=inteligencia&spell=1"> <strong> <em>inteligencia</em> </strong> </a>
Ahora sigamos mejorando nuestro script:
#importamos las librerias necesarias require 'open-uri' require 'rubygems' require 'hpricot' #tomamos el termino a buscar a traves de la linea de comando search_word = ARGV[0] url = "http://www.google.com.ar/search?q=#{search_word}" #creamos un objeto hpricot a partir de la url doc = Hpricot(open(url)) #buscamos dentro de la estructura de arbol #hasta el lugar que queremos y dado que la #busqueda en un documento devuelve un array #solo tomamos el primer elemento suggestion = (doc/"div#res/p/a/b/i").first #por ultimo pasamos la sugerencia a texto plano # y la mostramos a menos que google no nos haya sugerido nada puts "Quizás quiso decir: " + suggestion.to_plain_text unless suggestion.nil?
Para los fanáticos de realizar todo en una sola línea de código, les mostramos como hacer en dos líneas este programa (sin contar los “require”).
suggestion = (Hpricot(open("http://www.google.com.ar/search?q=#{ARGV[0]}"))/"div#res/p/a/b/i").first puts "Quizás quiso decir: " + suggestion.to_plain_text unless suggestion.nil?
Ahora sólo nos resta probar
alfredo@alfredo-laptop:~/dev/ruby$ ruby ud_quiso_decir.rb ruvy Quizás quiso decir: ruby alfredo@alfredo-laptop:~/dev/ruby$ ruby ud_quiso_decir.rb ruby alfredo@alfredo-laptop:~/dev/ruby$
Esta poderosa librería no sólo permite parsear HTML sino tambien archivos XML y lo que mostramos acá es sólo una pequeña parte de todas sus funcionalidades que vamos a seguir profundizando en futuros posts.
El código fuente del ejemplo puede bajarse desde aquí


