RGhost Barcode no Github
Monday, December 29th, 2008Onde 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. ![]()
HashCodeAn organizer of symbols
|
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. ![]()
Depois de muita enrolação, configuração e formatação acabo de colocar o RGhost no Github, vou manter o código lá e as gems continuarão no Ruby Forge pois no Github não está funcionando direito.
Criei umas 40 páginas de wiki(em inglês) e prometo(juro) que vou colocar mais exemplos.
Vou tentar migrar o RGhost Barcodes ainda este ano(eu acho).
Gostaria de agradecer a toda comunidade nacional e internacional que colaboram dando dicas e reportando bugs. Obrigado a vcs!
Já está disponível RGhost 0.8.6, compatível com Prawn e Ruport, isto é, agora você pode fazer seu benchmark sem precisar desinstalar o RGhost para usar o Prawn ou vise-versa.
A outra novidade é o ganho de 50 milissegundos pra cada template(EPS) renderizado, tal façanha pode não parecer muita coisa mas se seu documento tiver 100 páginas, são 5 segundos a menos(tempo de um gole de cerveja). Isso devido a criação de uma nova forma de vetorizar fontes em Postscript.
Divirtam-se e ganhem dinheiro!
Acabei de atualizar o RGhost para a versão 0.8.5, adicionei novas features e correção de uns bugzinhos, abaixo as principais mudanças.
Detecta e configura o path do ghostscript automaticamente para MacOS e Linux, avisa quando não detectou o executável e avisa o cara, com abaixo
Ghostscript not found in your environment. Install it and set the variable RGhost::Config::GS[:path] with the executable path. Example: RGhost::Config::GS[:path]='/path/to/my/gs' #unix-style RGhost::Config::GS[:path]="C:\\gs\\bin\\gswin32c.exe" #windows-style
Para windows vou fazer depois mais pode configurar manualmente.
Permite configurar a qualidade final do PDF que podem ser
Use o parâmetro :quality no método render
doc=RGhost::Document.new doc... #algo aqui doc.render :pdf, :quality => :ebook
Declara informações sobre o documento
Nas propriedades aparecerá

Usando o novo método Document#info
doc.info :Title => "My Report about XXX", :Author => "Company XXX", :Subject => "RGhost new version", :Creator => "We system", :Keywords => "foo bar bas to search enginers"
Carregamento de fontes externas via método tag com a opção :from
doc.define_tags do tag :one_font, :name => "HelveticaOblique", :size => 12 tag :another, :name => "Monaco", :size => 30 , :from => "/tmp/monaco.ttf" end
Agora permite atribuir uma senha para usuários e para o dono do documento essa senha desabilita opções de abertura, impressão etc. O código fica da seguinte forma
doc.security do |sec| sec.owner_password ="testXXX" sec.user_password ="testYYY" sec.disable :print, :copy end
Acima estou desabilitando a impressão e a cópia do conteúdo. Agora desabilitando tudo
doc.security do |sec| sec.owner_password ="test123" sec.user_password ="test567" sec.disable :all end
Quando o documento for aberto uma senha será solicitada.
A senha com total privilégio e a do “owner” e limite total para “user”.
O campeão de pedidos o hyperlink. Criado com base na clase text_in e bem simples de usar
doc.text_link "Click here",:url => "http://mysite", :tag => :link, :color => :blue
Posicionamento absoluto
doc.text_link "Click here",:x=> 2, :y=> 4, :url => "http://mysite"
Exemplo de um link que checa informações online do PDF.

Ou defina um retângulo clicável

Com o simples código
doc.rectangle_link :url=> "http://www.hashcode.eti.br", :width => 10, :height => 5, :x => 5,:y => 22, :color => :blue
Crie suas grids usando um bloco dentro do documento, veja
doc.rails_grid :style => :border_lines, :width => 4 do |grid| grid.column :title, :title => "Título", grid.column :name, :title => "Comentário", :format => lambda {|s| s.gsub(/^(.{20}).*$/,'\1...')} grid.column :created_on, :title => "Data", :format => lambda {|s| s.strftime("%d %b")} grid.data Post.find(:all, :limit => 100) end
gem install rghost
Espero que gostem!
Abaixo instruções de instalação do RGhost no MacOS
Requirimentos:
- Ruby
- RubyGems
- Xcode
- Mac Port
Primeiro instale o Ghostscript via macport
sudo port install ghostscript
Agora RGhost
sudo gem install rghost
Agora precisamos saber onde o executável do Ghostscript foi instalado para isso execute
hashcode:tmp shairon$ type gs gs is /opt/local/bin/gs
Observe que na minha instalação o path ficou /opt/local/bin/gs.
Vamos configurar e testar em um arquivo .rb ou via IRB
require 'rubygems' require 'rghost' #use o path do seu gs aqui RGhost::Config::GS[:path]="/opt/local/bin/gs" RGhost::Config.is_ok?.render :pdf, :filename => "/tmp/is_ok.pdf"
Uma página será gerada como essa

Em breve no manual em English.
Rubeiros,
Publiquei hoje um nova versão do RGhost http://rghost.rubyforge.org totalmente refatorada.
Bati forte em desempenho e na doçura da sintaxe, ficando mais fácil programar em Ruby e gerar códigos em Postscript.
Fiz um teste estuprador até 10K páginas com template e passou legal.
Abaixo algumas das mudanças.
Se alguém se interessar por traduzir o manual em português é só enviar um email para mim em pvt que eu mando o odt.
Agradeço a todos que reportaram bugs e me ajudaram a testar.
Desculpem a demora. Espero que gostem.
Depois de uma escravização no fim do ano passado e no inicio deste, estou de volta para “espalhar a maldade”!
Vou falar sobre PL/Ruby ou melhor fazer funcionar.
PL/Ruby é uma linguagem procedural acoplada dentro do Postgresql. Entre as linguagem do Postgres é a mais flexível e fácil.
Demonstrarei inicialmente “o jeitão da coisa” e depois uma implementação distribuída.
Instalação
Instale o banco e o módulo plruby, se o postres já estiver instalado, instale apenas o módulo(claro!)
apt-get install postgresql-8.1 postgresql-8.1-plruby
Agora conecte via psql
psql template1
Criaremos um banco novo para todos os testes deste tutorial, o banco “ruby_test”, então vamos lá
template1=# create database ruby_test;
conecte no banco novo
template1=# \c ruby_test
Crie a função/linguagem via o script plruby.sql que faz parte do pacote postgresql-8.1-plruby, se a sua distro difere de ubuntu, verifique onde o arquivo plruby.sql está e invoque com \i semelhante ao exemplo abaixo.
ruby_test=# \i /usr/share/postgresql-8.1-plruby/plruby.sql
Jeitão
Para familiarizarmos um pouco vamos criar uma função que produz uma seqüencia de números separados por espaço.
Portanto a função abaixo cria um Range do primeiro argumento(args[0]) até o segundo argumento(args[1]), converte o range para Array e depois para String separando os elementos por espaço.
create or replace function string_array(int,int) returns text as $RUBY$ (args[0]..args[1]).to_a.join " " $RUBY$ language plruby;
Executando
ruby_test=# select string_array(10,20);
Produzindo
"10 11 12 13 14 15 16 17 18 19 20"
Agora uma função que procura um padrão dentro do um texto, se o padrão for encontrado, o mesmo ficará entre tags <b>.
create or replace function find(varchar,text) returns text as $RUBY$ args[1].gsub(/(#{args[0]})/,'<b>\1</b>') $RUBY$ language plruby;
ruby_test=# select find('[tT]he','The method PL#context and PL#context= give the possibility to store information between the call')
Produto
"<b>The</b> method PL#context and PL#context= give <b>the</b> possibility to store information between <b>the</b> call"
Até agora demonstramos duas funções, faz uma lógica e retorna apenas uma tupla.
Ficou bem elegante essa implementação do PL/Ruby para vários registros(setof) sendo que cada registro é um objeto lançado pelo operador yield do Ruby.
Uma função em PL/Ruby para resolver a função(x ao quadrado vezes a raíz de 2)
f(x) = x^2 * raiz(2)
sendo x inteiro variando de x1 a x2.
create or replace function fx(int,int) returns setof float as $RUBY$ (args[0]..args[1]).each {|x| yield x.to_i**2 * Math.sqrt(2) } $RUBY$ language plruby;
Executando com * from pois estamos pegando vários registros
ruby_test=# select * from fx(1,10);
Resultando em
1.4142135623731 5.65685424949238 12.7279220613579 22.6274169979695 35.3553390593274 50.9116882454314 69.2964645562817 90.5096679918781 114.551298552221 141.42135623731
Manipulando dados
Vamos criar uma tabela denominada “users” para povoarmos de dados para os testes.
ruby_test=# CREATE TABLE users( id serial not null primary key, name varchar(255) not null , login varchar(80), email varchar(80), password varchar(80) ) ;
Inserindo alguns registros
ruby_test=# insert into users(name,login,email,password) values ('Fulano de tal','fulano','fulano@server.com','fulanopwd');
ruby_test=# insert into users(name,login,email,password) values ('Maria da Silva','maria','maria.silva@server.com','mariapwd');
ruby_test=# insert into users(name,login,email,password) values ('Sem nome','semnome','semnome@server.com','semnomepwd');
Daqui a pouco faremos a distribuição dos dados via trigger para bancos remotos, portanto criaremos uma função para criação dos inserts.
A função make_insert faz engenharia reversa na ddl e nos dados utilizando o módulo PL disponível no plruby
CREATE OR REPLACE FUNCTION make_insert(users) RETURNS text AS $RUBY$ row=args[0] tn=PL.args_type.to_s cn=row.keys.join(',') values= row.values.map{|m| (m)?"'#{m}'":'NULL' }.join(',') "INSERT INTO #{tn}(#{cn}) values (#{values})" $RUBY$ language plruby;
Veja o exemplo da execução
ruby_test=# select make_insert(users) from users;
Resultado
INSERT INTO users(name,id,password,login,email) values ('Fulano de tal','1','fulanopwd','fulano','fulano@server.com')
INSERT INTO users(name,id,password,login,email) values ('Maria da Silva','2','mariapwd','maria','maria.silva@server.com')
INSERT INTO users(name,id,password,login,email) values ('Sem nome','3','semnomepwd','semnome','semnome@server.com')
Sem aquela concatenação demasiada do plpgsql usando pipes e aspas para todo lado. Ah! a função make_insert é genérica para qualquer tabela mas no argumento de criação a sua tabela. Tipo
CREATE OR REPLACE FUNCTION make_insert(sua_tabela) RETURNS text AS $RUBY$ ...
Semelhante aos parâmentos tabela%rowtype do postgres.
Distribuindo os dados
Já vou dizendo logo, isso não é comparável ao Slony-I, isso é uma simples utilização do dblink do postgresql.
As funções de dblink ficam no pacote contrib do postgres, a instalação com apt-get
apt-get install postgresql-contrib-8.1
Crie as funções com \i onde o argumento é o arquivo dblink.sql
ruby_test=# \i /usr/share/postgresql/8.1/contrib/dblink.sql
Lembrando a assinatura da função dblink_exec é
select dblink_exec("connection string","query")
Exemplo
select dblink_exec('hostaddr=127.0.0.1 dbname=mydb user=shairon password=senha','insert into...');
Partiremos da seguinte extrategia: criaremos uma tabela chamada nodes onde armazenaremos os dados dos bancos de dados, selecionaremos apenas os nodes ativos e enviaremos os registros para os mesmos através da trigger replica_plruby(T) no evento after insert na tabela users master(A).
Veja o diagrama abaixo.

Então temos a tabela nodes.
create table nodes(id serial not null primary key, host varchar(80), username varchar(80), password varchar(80), active boolean )
Dados para teste
insert into nodes(host,dbname,username,password,active) values ('127.0.0.1','mydb1','foo','bar',true);
insert into nodes(host,dbname,username,password,active) values ('192.168.0.7','mydb2','foo','bar',true);
insert into nodes(host,dbname,username,password,active) values ('10.0.0.38','mydb3','foo','bar',true);
Criando a trigger replica_plruby, acompanhe pelos comentários
CREATE OR REPLACE FUNCTION replica_plruby() RETURNS trigger AS $RUBY$ #obtendo a quantidade de nós ativos count=PL::exec("select count(*) from nodes where active=true",1,"value").to_s.to_i if count > 0 #obtendo os nós ativos PL::Plan.new("select * from nodes where active=true").each do |row| #montando a conexão #cada row é um hash tipo {"dbname"=>"delme", "username"=>"shairon" ...} conn="hostaddr=#{row['host']} dbname=#{row['dbname']} user=#{row['username']} password=#{row['password']}" #Nome das culunas via metadata keys = new.keys.join(",") #Os valores com tratamento de nulo values = new.values.map{|m| (m)?"''#{m}''":'NULL' }.join(',') #Query final query = "INSERT INTO #{tg['relname']}(#{keys}) values (#{values})" #Disparo PL.exec("select dblink_exec('#{conn}','#{query}')") end end new $RUBY$ LANGUAGE plruby;
Pronto! Insira novos dados na tabela users para ver o resultado.
Referências
Nos arquivos de documentação dos pacotes
ruby1.8 postgresql-8.1 postgresql-8.1-plruby postgresql-contrib-8.1
Você escolhe!!

Pra quem pediu, disponibilizei o rghost como plugin no repositório do rghost no RubyForge só descompactar no RAILS_ROOT/lib e reiniciar a aplicação.
Geralmente as impressoras de médio e grande porte disponibilizam uma porta TCP conhecida como ‘porta bruta’ de número 9100. Demonstrarei aqui uma forma de imprimir diretamente neste tipo de printer, para o nosso exemplo usaremos o driver postscript genérico da Adobe(PS-Adobe-3.0).
Models Contas e Clientes
class Contas < ActiveRecord::Base belongs_to :clientes end class Clientes < ActiveRecord::Base has_one :contas end
Configurando as colunas
require 'rghost' clientes=Clientes.find :all, :include => :contas, :limit => 10000 grid=DataGrid::RailsGrid.new :width => 4 , :align => :center grid.col :codigo, :title => "Código do Cliente", :width => 5 grid.col :nome, :title => "Nome" grid.col :created_on, :title => "Data de Cadastro ", :format => :eurodate grid.col lambda { contas.login }, :title => "Login" grid.data(clientes)
Criando o documento com dados do ActiveRecord
doc=Document.new :paper => :A4, :landscape => true, :duplex => true doc.before_page_create do set Image.for("/tmp/fatura.eps") end doc.set grid doc.done
Enviando o documento
printer = TCPSocket.open('192.168.1.70', 9100) printer.write doc.render_stream(:ps)
Deve ter saído lá na impressora…
Para mais informações no RGhost - RubyForge . Documentação em português no RubyForge
Com a versão 0.7 podemos agora usar diferentes codificação de fontes e conversão de charset de Ruby para Postscript.
Encodings disponíveis
Ideal para código fonte Ruby no mesmo formato dos dados do documento. Existem duas formas de setar o encoding da fonte:
Antes de usar o documento
RubyGhostConfig::GS[:font_encoding] = 'CodePage1252'
Na criação do documento
doc=Document.new :font_encoding => 'CodePage1252'
Agora quando o charset do código fonte está diferente dos dados é necessário a conversão dos formatos. Para este fim usamos um bloco retornando uma string antes da criação do documento.
Exemplo para código fonte no padrão UTF-8 com acentuação.
RubyGhostConfig::GS[:charset_convert]= lambda {|text| Iconv::iconv('latin1','utf8', text).to_s}
O gem e o manual da versão 0.7 disponível no RubyForge.