Skip to content
Mar 28 11

82 Barcodes for Ruby on Rails

by shairon

I’ve just updated RGhost Barcode, I got last update from BWIPP Terry Burton code and I adapted it to RGhost Barcode v0.9.


RGhost and BWIPP have been created using postscript as core language, the integration is pretty easy to do, there are some advantages to using RGhost and RGhost Barcode(with BWIPP) to render barcodes, among them we can highlight:

  • All complexity is done in low-level, the code runs faster than using a pure-ruby code to do it.
  • It improves the backend performance using Ghostscript native libraries.
  • Many output formats are supported, such pdf, png, jpg, tif, ps, etc.
  • With RGhost templates and RGhost Barcode you can easily create pretty neat documents, using images, shapes, custom fonts and of course, your creativity.

New barcodes

Now it supports new 50 barcodes types, in a total of 82 barcodes, BWIPP supports more barcode formats than any other free or commercial software.
For most of types, only pass the barcode string then the method will render it properly.

The big list

Here is the list of supported barcodes

Installation

Use gem or bundler to install it, but make sure whether rghost version is >= 0.8 and rghost_barcode is >= 0.9.

gem install rghost
gem install rghost_barcode -v=0.9

A simple example using QRCode

require 'rghost'
require 'rghost_barcode'

RGhost::Document.new do |doc|
 doc.barcode_hibcqrcode "A123BJC5D6E71"
 doc.render :pdf, :filename => "my_nice_qrcode.pdf"
end

Need more Info

Barcode Writer in Pure PostScript
RGhost Barcode
RGhost
RGhost Rails

Enjoy it!

Mar 27 11

Objective-C Model Generator

by shairon

Ok, ok, I know, the name sounds like a big project but it isn’t. I created a private RESTful API in Objective-C last year(until January 2011), there is a piece of code that I can share with you. I was thinking in create a model generator similar of Rails scaffold and adapt it to IPhone on Rails. The idea is simple, from a command line to create a .h and .m based on parameters, I pushed the code to the git repo objc-generators.

How use it

Clone it

git clone https://github.com/shairontoledo/objc-generators.git

There is a directory called script, it should be placed in your project root or you can generate the files and copy them to your project manually.

So generate the model.

scripts/generate model Person name:string code:float thenumber:integer active:bool created_at:date updated_at:date

Does it look familiar to you?

The output

A .h file

#import <Foundation/Foundation.h>

@interface Person : NSObject {
  NSString *name;
  float code;
  NSInteger thenumber;
  BOOL active;
  NSDate *created_at;
  NSDate *updated_at;
}
@property(retain, nonatomic) NSString *name;
@property float code;
@property NSInteger thenumber;
@property BOOL active;
@property(retain, nonatomic) NSDate *created_at;
@property(retain, nonatomic) NSDate *updated_at;
@end

and its .c

#import "Person.h"

@implementation Person
@synthesize name, code, thenumber, active, created_at, updated_at;
- (id)init {
    if ((self = [super init])) {
        // Initialization code here.
    }

    return self;
}

- (void)dealloc {
    // Clean-up code here.

    [super dealloc];
}

It’s simple, I hope I get a time to improve it. Maybe it’s useful for you.

Jan 6 11

Hooks em Ruby

by shairon

Ruby é uma linguagem dinâmica e utiliza algumas caracteristicas interessantes para manipular objetos e classes no seu ciclo de vida em run-time, como por exemplo usar singleton methods em um objeto, realizar mixin, adicionar métodos em uma classe e outras coisas legais. Para capturar esse eventos que alteram o comportamento de classes, módulos e objetos, Ruby provê alguns Hooks.

O que seriam Hook propriamente dito(pergunta clássica no curso de metaprogramação)? Hooks são métodos com um nome específico para capturar um mudança no objeto. Esses hooks podem ser definidos por uma API ou mesmo pela a especificação da linguagem. Um exemplo de API que utilize hooks são os callbacks do ActiveRecord, como after_save, before_save, etc, esses métodos são invocados automaticamente após a chamada “save” do model como descrito na especificação.

Hooks da Linguagem Ruby

O intuito deste poste é falar sobre alguns hooks da linguagem Ruby, vamos iniciar capturando o evento de herança de uma classe, isso pode ser muito útil se sua super-classe precisa conhecer a subclass. Para esse hook funcionar temos que definir o método self.inherited na superclass. Exemplo

class A
  def self.inherited(subclass)
    puts "Eu #{self} sendo herdada por #{subclass}"
  end
end

class B < A
end

#=> "Eu A sendo herdada por B"

O conteúdo do método inherited é executado pelo interpretador no momento em que a sub classe é carregada na vm. Lembra do final public class A{} em java? Para quem nunca usou java o final public class é forma de não permitir que uma classe seja herdada por outra. Em ruby você pode simular esse comportamento lançando uma exceção dentro do self.inherited, veja:

class A
  def self.inherited(subclass)
    raise "A classe #{self} nao pode ser herdada!"
  end
end

class B < A
end 

#E=> RuntimeError: A classe A nao pode ser herdada!
 

self.included

O self.inherited é usado apenas para classes, se você precisar detectar mix-in entre módulos e classes, defina o método self.included dentro do módulo que será mixado. O exemplo abaixo demonstra como capturar o evento de mix-in(include):

module M
  def self.included(from)
    puts "#{self} foi mixado por #{from} "
  end
end

class A
  include M
end

Particularmente acho o self.included muito útil, com ele podemos adicionar funcionalidades durante o mix-in. Por exemplo, vamos criar um plugin chamado Printable, na verdade é só um módulo com um pouco de metaprogramação para detectar os accessor(setters e getters) e definir um novo método com o prefixo print_ para imprimir o retorno do método original, seria basicamente assim.

class Person
  attr_accessor :name, :code
end

p = Person.new
p.name ="Foobar"
p.print_name #ainda não existe

Vamos detectar os accessor, se um método tem dois métodos com o mesmo nome mas sendo um terminado com o operador de atribuição(=) então é um acessor.

Antes vamos criar a funcionalidade apenas para classe Person

class Person
  attr_accessor :name, :code
end

#pegando os métodos de instância
methods = Person.instance_methods false
#=> ["code", "name=", "code=", "name"]

#detectando quais deles são accessors
 acessors=methods.select{|m| methods.include? "#{m}=" }
#=> ["code", "name"]

#definindo os métodos na classe
acessors.each do |acessor|
  Person.send :define_method, "print_#{acessor}" do
    puts "Printing #{send(acessor)}..."
  end
end

#Testando
p = Person.new
p.name = "FFUUUU"
p.code = 44444
p.print_name  #=> Printing FFUUUU ...
p.print_code  #=> Printing 44444 ...

Perfeito! Agora vamos criar um módulo e utilizar o hook self.included, com isso, quando uma classe necessitar dessa funcionalidade é só fazer o include de Printable, veja

module Printable
  def self.included(klazz)
    methods = klazz.instance_methods false
    acessors=methods.select{|m| methods.include? "#{m}=" }
    acessors.each do |acessor|
      klazz.send :define_method, "print_#{acessor}" do
      puts "Printing #{send(acessor)}..."
    end
  end
end

Fazendo mix-in em Person e em OtherClass

class Person
  attr_accessor :name, :code
    include Printable
  end

class OtherClass
  attr_accessor :a, :b
  include Printable
end

Testando

p = Person.new
p.name = "FOO"
p.print_name

obj = OtherClass.new
obj.a = "Hey Everybody!"
obj.b = "It's working"
obj.print_a
obj.print_b

Output

Printing FOO...
Printing Hey Everybody!...
Printing It's working...

self.method_added

Se você leu esse post até aqui provavelmente você conhece o method_missing, aquele que captura a nome do método e os parâmetros caso o objeto não responda a esse método. Pois é, não falaremos do method_missing nesse post, vamos falar do primo dele, o self.method_addded. O self.method_added é um hook que captura o evento quando um método é adicionado ao objeto ou classe. Exemplo.

class Foo
  def self.method_added(method)
    puts "Adicionado o metodo #{method} na classe #{self}"
  end

  def testing
    puts "testing"
  end
end
 #=> "Adicionado o metodo testing na classe Foo"

Veja que na própria classe o evento é disparado. Em uma herança, o mesmo comportamento

class Foo
  def self.method_added(method)
    puts "Adicionado o metodo #{method} na classe #{self}"
  end
end

class Bar < Foo
  def other_method
    puts "say hello"
  end
end

#=> Adicionado o metodo other_method na classe Bar

Ou ainda, você pode capturar singleton methods com o mesmo hook.

class Foo
  def self.method_added(method)
    puts "Adicionado o metodo #{method} na classe #{self}"
  end
end

foo = Foo.new

def foo.new_method
  puts "hey I'm adding ..."
end

Object.const_missing

Sabemos que o method_missing captura o evento quando o método não existe, podemos ter uma funcionalidade semelhante para constantes, com o Object.const_missing. Sempre que uma constante não for encontrada na vm, o const_missing recebe o nome da constante. Esse método deve ser definido em Object, dado que constantes o escopo é global. Veja

UmaConstante #E=> NameError: uninitialized constant UmaConstante

def Object.const_missing(const)
  puts "Hey nao encontrei #{const} mas nao vou lançar error"
end 

UmaConstante
#=> Hey nao encontrei UmaConstante mas nao vou lanar error

Embora isso seja uma coisa legal, se você apenas quer capturar o evento, uma boa prática é fazer a sua lógica usando a constante que está faltando e depois usar o super para lançar a exceção via Kernel. Portando algo como

UmaConstante #E=> NameError: uninitialized constant UmaConstante

def Object.const_missing(const)
  puts "Hey nao encontrei #{const} "
  super
end 

UmaConstante

#=> Hey nao encontrei UmaConstante
#=> NameError: uninitialized constant UmaConstante
#=>	 from (irb):119:in `const_missing'
#=>	 from (irb):122
#=>	 from :0

Se seu é convencionado utilizando o nome do arquivo em snake case e o nome da classe em camel, você pode fazer um plugin para carregar seus arquivos automaticamente caso a classe não esteja visível no trecho do seu código. Exemplo, no mesmo diretório 3 arquivos

Arquivo person.rb

class Person
  attr_accessor :name, :state
end

Arquivo state.rb

class State
  attr_accessor :code
end

Arquivo principal main.rb

p = Person.new
p.state = State.new

Rode com

ruby main.rb

De cara o erro

#E=> main.rb:1: uninitialized constant Person (NameError)

Pois não colocamos o requires necessários para cada arquivo.
Vamos fazer um algoritmo para carregar esses arquivos automaticamente usando Kernel.autoload.
Então no main.rb fica com o conteúdo:

def Object.const_missing(const)
  #convertendo CamelCase to snake_case
  filename = const.to_s.gsub(/([A-Z])/, ' \1').split(' ').join('_').downcase
  #Associando a constante ao nome do arquivo
  autoload const, filename
  #binding a nova constante
  Object.const_get const
end  

p = Person.new
p.state = State.new

Se você rodar novamente o main.rb vai funcionar.

Conclusão

No dia-a-dia e em projetos pequenos não é comum capturar eventos no nível de interpretação mas se você esta depurando um sistema ou mesmo desenvolvendo uma API, Hooks podem ser essenciais.

Dec 13 10

Replicando Memcached com Rails 3

by shairon

Um dos fatores de qualidade de SaaS é eliminar os SPOFs ganhando assim alta disponibilidade do serviço para o usuário final. A regra é simples, se tem algo no sistema que é único, tenha uma backup desse serviço, a.k.a redundância. Exemplo dois ou mais replicas de banco de dados, mais de um servidor http, mais de um worker e etc.
Na modalidade de negócios Saas isso significa credibilidade e deve ser mantida no mais alto nível quanto possível. Quando há uma falha crítica o cliente não quer saber se o correu falha humana, falha no banco, falha no hosting, no storage ou qualquer outro componente da solução, o cliente quer a informação no momento do acesso. Quaisquer tipo de transtorno causados no acesso dessa informação custa caro para empresa, é um chamado a mais para um atendente, é um ticket a mais para você solucionar.

E a sorte nunca esta do lado executivo-da-força, se tem algo pra dar problema… vai acontecer hoje ou outro dia. Isso não é pessimismo, isso é realidade do dia-a-dia em tentar deixar uma big aplicação Always on no cloud.

Falando em cloud e indo para um nível baixo, na comunidade Ruby on Rails existe muito barulho na parte de escalabilidade, aquela velha história do “O Rails não escala”, não continuarei esse briga aqui… o intuito desse post é compartilhar uma estrutura que estamos usando aqui na OfficeDrop para manter a sessão do usuário mesmo se houver um erro tanto no memcached master ou se houver uma sobrecarga no uso do mesmo.

O workflow de sessão

O fluxo de utilização do memcached pelo Rails é bem simples. O memcache-client instanciado no Rails estabelece um conexão TCP/IP(pode utilizar UDP também) com o memcached, considerando uma conexão ativa ente eles, você pode utilizar vários comandos disponíveis no memcache-client que na verdade é um wrapper facilitador. Se você for curioso o bastante inicie o memcached e teste-o com o telnet.

Inicie com very verbose mode pra ver as mensagens sendo trocadas pelo protocolo

 memcached -vv

Obs: estou considerando o memcached instalado no seu sistema.

A porta padrão do memcached é 11211

telnet localhost 11211

Com a conexão ativa você pode executar comandos como o set para armazenar uma valor utilizando uma chave como indexado.

 set msg 0 0 7
 diga oi

As duas linhas acima estão dizendo “utilize a chave “msg” com flag 0 (o primeiro), sem tempo de expiração (o segundo 0 ) com o valor ‘diga oi’ com o comprimento 7 (length)”. Para obter o valor, use get com a chave e comprimento do valor.

get msg 7

ficando assim seu shell

telnet localhost 11221
Trying ::1...
Connected to localhost.
Escape character is '^]'.
set msg 0 0 7
diga oi
STORED
get msg 7
VALUE msg 0 7
diga oi
END

Dê uma olhada aqui para saber sobre mais comandos.

Na Prática

É bem popular a utilização do memcached no rails mas tem um problema na utilização padrão. Mesmo configurando um failover em um array de servidores ["mem1:11211", "mem2:11212"] isso não garante, por exemplo, que a sessão do usuário iniciada no mem1 será mantida no servidor mem2 se houver uma queda no mem1. Então, falhando mem1 o usuário terá que logar novamente, mas dessa vez usando o mem2.

Repcached

Para evitar que o usuário tenha esse desprazer de logar novamente utilizamos o Repcached.

O Repcached é um patch para lidar com replicação multi-master assíncrona, multi-master aqui quer dizer, mem1 replicará para mem2, se mem1 falhar mem2 receberá as novas requisições e quando o mem1 tonar ativo o mem2 enviará os dados para o mem1.

Cenários

Cenário 1 – Apenas uma VM
Ideal se o seu sistema só tem um servidor.

Não é tão ideal assim, se seu sistema só tem um servidor … repcached não resolve muito o seu caso. Você usaria repcached apenas para redundar o servidor master na mesmo host.

Cenário 2 – Dois ou mais VMs

Ideal para sistema médio ou grande. Com essa configuração cada instância do Rails utilizará o memcached na máquina local e o failover para o servidor central. Então quando o usuário inicia a sessão no repcached1 e por acaso venha a falhar a sessão pode ser retomada usando o repcached2.

Para os dois cenários a configuração é a mesma, mudando apenas os IPs.

Compilando

A instalação é bem simples apenas com libevent como dependência, a compilação abaixo é para MacOS, se você esta usando linux verifique no seu gerenciador de pacote como instalar libevent no seu sistema.

Instale libevent

sudo port install libevent

Baixe, descompacte e entre no diretório que foi criado

wget http://sourceforge.net/projects/repcached/files/repcached/2.2-1.2.8/memcached-1.2.8-repcached-2.2.tar.gz/download
tar zxf memcached-1.2.8-repcached-2.2.tar.gz
cd memcached-1.2.8-repcached-2.2

No configure, passe o flag --enable-replication

./configure --prefix=/opt/local --enable-replication

Compile e instale

sudo make install

Observe o destino em que o repcached foi instalado, observe também que o nome do executável é o mesmo do memcached. Lembrando… repcached é o memcached com patch para replicação.

/usr/bin/install -c 'memcached' '/opt/local/bin/memcached'
/usr/bin/install -c 'memcached-debug' '/opt/local/bin/memcached-debug'

Se você achar melhor, crie um alias

alias repcached=/opt/local/bin/memcached

Após a instalação execute o repcached com -h, nas duas primeiras linhas o memcached original e o repcached.

/opt/local/bin/memcached -h
memcached 1.2.8
repcached 2.2

E nas últimas linhas o -x host e -X port para a replicação

-x   hostname or IP address of peer repcached
-X       TCP port number for replication (default: 11212)

Veja que a porta de replicação padrão é 11212, então nenhum memcached poderá ser iniciado na mesma.
Configure /etc/hosts para ambas as VMs

192.168.20  mem1
192.168.20  mem2

Iniciando os servidores

Vamos iniciar o primeiro servidor, o mem1, -p(TCP port 11220) e -U (UDP port 11220) são parâmetros para o memcached local, -x (ip mem2) e -X (port 11230) são parâmetros para replicação. Então, no mem1 o comando é.

memcached -vv -p 11220 -U 11220 -x mem2 -X 11230

Observe que na inicialização aparecerá o servidor de replicação utilizado

replication: connect (peer=mem2:11230)
replication: marugoto copying
replication: close
<5 connection closed.

Mas com a replicação inativa.
Agora na mem2, inicie o memcached apontando pra mem1

memcached -vv -p 11220 -U 11220 -x mem1 -X 11230

Agora, o mem2 ativa a replicação

replication: connect (peer=mem1:11230)
<4 new client connection
replication: marugoto copying
<4 marugoto_end
<7 server listening
<8 server listening
<9 send buffer was 9216, now 3728270
<9 server listening (udp)
<10 send buffer was 9216, now 3728270
<10 server listening (udp)
replication: start

Se você der uma olhada no mem1 depois de iniciar a replicação no mem2 o handshake começa.

<4 server listening (replication)
<5 server listening (replication)
replication: listen
<6 server listening
<7 server listening
<8 send buffer was 9216, now 3728270
<8 server listening (udp)
<9 send buffer was 9216, now 3728270
<9 server listening (udp)
replication: accept

Configurando o Rails 3.0.3

Dado que os servidores estão configurados vamos para o Rails. Utilizaremos o Rails 3 para o teste. Então no Gemfile use

gem "memcache-client"
gem 'memcached-northscale', :require => 'memcached'

Execute o bundle

bundle install

Configure os servidores no config/environment.rb, com opções essenciais, habilitando multi-thread, compressão para grande quantidade de dados e os servidores. Usei o nome App para a aplicação então o arquivo config/environment.rb fica parecido com:

require File.expand_path('../application', __FILE__)

RAILS_CACHE  = Memcached::Rails.new {
  :compression => true,
  :multithread => true,
  :servers => ['mem1:11211','mem2:11211']
}

# Initialize the rails application
App::Application.initialize!
App::Application.config.cache_store = :mem_cache_store
App::Application.config.session_store(:mem_cache_store, :cache => RAILS_CACHE)

O teste

Você pode testar criando um scaffold usando session[] mas aqui vou usar o console pra demonstrar a replicação. Um simples teste,

1. Usar Rails.cache
2. Armazenar um valor
3. Fechar o mem1
4. Ler o valor

Então abra o console e verifique se o Rails.cache esta usando o memcache-client

rails console
Loading development environment (Rails 3.0.3)
>> Rails.cache.class
=> Memcached::Rails

Armazenando um valor

>> Rails.cache.set "message", "oi tudo bem?"
=> true

No STDOUT do mem1 você verá algo como

<11 set mytestmessage 0 604800 16
>11 STORED

e no mem2

<10 rep mytestmessage 0 1292878695 16 2
REP>10 STORED

Agora feche o mem1, volte no console do rails e leia o valor

>> Rails.cache.get "message"
=> "oi tudo bem?"

Hmm então funcionou!

No mem2 você verá que o repcached está tentando replicar para mem1. Como o memcached é volátil quando o servidor memcached é fechado todas as chaves são perdidas mas como a replicação esta ativa e o mem2 tem as chaves, no ato de iniciar o mem1 novamente, mem2 sincronizará as chaves e os valores com mem1.

replication: marugoto copyinga
<4 rep mytestmessage 0 1292878695 16 2
REP>4 STORED
<4 marugoto_end

Então é isso, se você precisar de esteroides na sua sessão da sua aplicação... repcached é uma boa pedida.

A gem memcached-northscale tem várias opções de configuração do memcached no rails, recomendo a leitura da documentação que esta em rdoc.

Outra opção seria o Redis talvez em outro momento eu posto algo sobre ele.

Dec 3 09

Quando o RAID não funciona

by shairon

Ok esse não era pra ser o primeiro post do ano de 2009 mas o “RAID” do meu antigo provedor(que era cortesia) deu pau.


Como diria o velho ditado modificado “na casa do espeto o churrasqueiro é de pau” eu tinha um script na cron fazendo backup diário mas o que eu não tinha percebido era que minha chave publica tinha sido modificada :( .

Recebi alguns emails de pessoas querendo acessar alguns links então acho que esse blog pode ser de certo modo útil.

Jan 16 09

Diário de um desenvolvedor by Daft Punk

by shairon

Nada mais que a verdade :) Só faltou commit it, push it, list it …

Buy it, use it, break it, fix it,
Trash it, change it, mail – upgrade it,
Charge it, point it, zoom it, press it,
Snap it, work it, quick – erase it,
Write it, cut it, paste it, save it,
Load it, check it, quick – rewrite it,
Plug it, play it, burn it, rip it,
Drag and drop it, zip – unzip it,
Lock it, fill it, call it, find it,
View it, code it, jam – unlock it,
Surf it, scroll it, pause it, click it,
Cross it, crack it, switch – update it,
Name it, rate it, tune it, print it,
Scan it, send it, fax – rename it,
Touch it, bring it, Pay it, watch it,
Turn it, leave it, start – format it.

Remix

Jan 7 09

Instalando RGhost com Debgem no Ubuntu Hardy

by shairon

Acho que foi ontem que eu vi sobre o projeto DebGem dos caras da Phusion. O projeto consiste em portar uma gem para um pacote .deb. Fui testar achando que iria dar o maior pau mas eu estava errado, funcionou plug’n'play. O que eu fiz foi basicamente descrito abaixo.

Configurando o apt-get

Configurei o novo source para o apt-get colocando no arquivo /etc/apt/source.list a nova entrada

 deb http://www.debgem.com/apt ubuntu-8.04 rubyforge

No shell adicionei a nova chave

wget -q http://www.debgem.com/apt/debgem.gpg -O- | sudo apt-key add -

e por fim, atualizei o apt-get

sudo apt-get update

Tudo isso está bem documentado aqui

Obtendo o nome do pacote

Entre no site http://www.debgem.com/usage e digite o nome da gem, no nosso caso ‘rghost’, aparecerá uma página com o nome e a descrição da gem

Observe a linha Install command apt-get install librghost-ruby , instale com

sudo apt-get install librghost-ruby

Testando

Abra o irb ou crie um arquivo para testar

require 'rubygems'
require 'rghost'

RGhost::Config.is_ok? :render => "/tmp/test.pdf"

`evince /tmp/test.pdf`

Conclusão

Perfeito! Não há nada que reclamar :)

Jan 3 09

IRB com reverse search no Apple Terminal

by shairon

Após muitas tentativa achei uma solução plausível, agora o meu irb aceita Ctrl+R. Solução simples
Edite o ~/.editrc e cole

bind "^R" em-inc-search-prev

Que saudade do gnome-terminal …

Dec 29 08

RGhost Barcode no Github

by shairon

Onde posso encontrar 32 tipos de código de barras, de graça? Tenho que gerar em PDF ou imagens?

A solução está aqui no GitHub RGhost Barcode

Poli-hashcode sempre uma solução para salvar sua vida. :)

Dec 29 08

Firulando código em ruby para wordpress

by shairon

Ultimamente estou recebendo emails me perguntando qual o plugin do WordPress eu uso para deixar o código do meu blog ‘bonitinho’. Já enviei uns 6 emails para pessoas diferentes, já que o pessoal está gostando vou postar a minha solução.

Criei um programinha que chamei de compile_post.rb ele recebe um arquivo texto e formata as tags code para html.

O programa requer as gems hpricot e syntax, para instalar basta

sudo gem install hpricot
sudo gem install syntax

O conteúdo é esse

#!/usr/bin/ruby
require 'rubygems'
require 'hpricot'
require 'syntax/convertors/html'

convertor = Syntax::Convertors::HTML.for_syntax "ruby"
source=ARGV[0]

abort "usage: ruby compile_post.rb filename.txt" unless source

doc = Hpricot.parse(File.readlines(source).join)
(doc/"code").each do |c|
   c.inner_html=convertor.convert(c.to_s.gsub(/<code>|<\/code>/,''),true)
end
File.open("#{source}.post",'w'){|f| f.puts doc.to_s.gsub(/<code>|<\/code>/,'') }

O programa gerará um arquivo .post é só copiar e colar no post editor do WordPress

Criei também um estilo meia-boca TextMate-like. Não se esqueça de

<link href="http://yoursite.com/mate.css" rel="stylesheet" type="text/css" media="all" />