HashCode

An organizer of symbols

Archive for the ‘Coisas’ Category

Quando o RAID não funciona

Thursday, December 3rd, 2009

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.

Diário de um desenvolvedor by Daft Punk

Friday, January 16th, 2009

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

Instalando RGhost com Debgem no Ubuntu Hardy

Wednesday, January 7th, 2009

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 :)

Firulando código em ruby para wordpress

Monday, December 29th, 2008

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" />

ActiveRecord ParseLine no GitHub

Sunday, December 28th, 2008

ParseLine no GitHub.

Versão em Português aqui

Para arquivos offline use a gem Parseline

Friday, November 14th, 2008

Parsear um arquivo texto em Ruby é algo fácil, persistir os dados no banco com Rails é trivial.
Vou demostrar como carregar arquivos csv e arquivos com layout largura fixa no braço, e mais a frente a nova gem Parseline.

Caso 1: Largura fixa

Suponhamos que seja necessário carregar dados de produtos de um arquivo denominado “data.txt” com o conteúdo

000001PRODUTO 1       S 21/11/2008000090.00
000002PRODUTO 2       N 22/11/2008000341.33
000003PRODUTO 3       N 01/11/2008000001.99
000004PRODUTO 4       S 15/11/2008000034.98
000005PRODUTO 5       N 14/11/2008000130.44
000006PRODUTO 6       S 05/11/2008000020.11

sendo o layout definido dessa forma:
- posição 0 até 5 = código do produto 00221
- posiçao 6 até 21 = nome do produto
- posição 22 = ‘S’ se tem em estoque e ‘N’ não tem
- posição 23 = reservado para uso futuro
- posição 24 até 33 = a data do cadastro
- posição 34 até 42 = preço do produto

Nossa tabela/model será Product definida por

class CreateProducts < ActiveRecord::Migration
  def self.up
    create_table :products do |t|
      t.integer  :code
      t.string  :name
      t.boolean :in_stock
      t.date    :date
      t.float   :price
    end
  end

  def self.down
    drop_table :products
  end
end

Vamos percorrer cada linha do arquivo fazendo parser dos campos, como descrito no layout acima

File.readlines('data.txt').each do |line|
  line.strip! #retirando caracteres não imprimiveis
  #definindo os campos
  code    = line[0..5]
  name    = line[6..21].strip
  in_stock   = line[22..22]
  nothing = line[23..23]
  date    = line[24..33]
  price   = line[34..42]
  #trantando os dados
  in_stock=(in_stock=='S') #=> true se 'S', false se 'N'
  date=date.split(/\//).reverse.join('-') #=> formata data para '2008-11-05'

  #attribuindo os valores no AR
  product=Product.new :code => code,
                      :name => name,
                      :in_stock => in_stock,
                      :date => date,
                      :price => price
  product.save # salvando :)                     

end

Pronto, tá lá no banco.

Caso 2: Arquivos CSV

Arquivos delimitados por um caracter geralmente , ou ;
Esse será o nosso arquivo “data.csv” com o conteúdo

1;PRODUTO 1;S;;21/11/2008;90.00
2;PRODUTO 2;N;;22/11/2008;341.33
3;PRODUTO 3;N;;01/11/2008;1.99
4;PRODUTO 4;S;;15/11/2008;34.98
5;PRODUTO 5;N;;14/11/2008;130.44
6;PRODUTO 6;S;;05/11/2008;20.11

temos o layout para cada linha

código do produto;nome;se tem em estoque;*reservado*;data;preço

Utilizaremos a mesma migration CreateProducts. Vamos ao código

File.readlines("data.csv").each do |line|
  #definindo os campos
  code,name,in_stock,nothing,date,price = line.strip.split(';')

  #trantando 
  in_stock=(in_stock=='S') #true se 'S', false se 'N'
  date=date.split(/\//).reverse.join('-') #formata data para '2008-11-05'

  #atribuindo os valores
  product=Product.new :code => code,
                      :name => name,
                      :in_stock => in_stock,
                      :date => date,
                      :price => price

  product.save                      

end

Nova gem ParseLine

O que ela faz? Nos ajuda a carregar dados externos de arquivos offline de uma forma mais elegante.
Suporta CSV ou largura fixa.

Funcionamento

Basta extender o módulo ParseLine::CSV ou ParseLine::FixedWidth e definir o layout.

Caso 1: Largura fixa

Utilizaremos o módulo ParseLine::FixedWidth com o arquivo “data.txt”, a sintáxe é

  parse.field :nome_do_campo, intervalo, lambda{|campo| fomatador}

Olha como é simples

require 'parseline'

class Product < ActiveRecord::Base
  extend ParseLine::FixedWidth
  fixed_width_layout do |parse|
    parse.field :code , 0..5
    parse.field :name,  6..21
    parse.field :in_stock, 22..22, lambda {|f| f == 'S' }
    parse.field :date , 24..33,    lambda {|d| d.split(/\//).reverse.join('-') }
    parse.field :price, 34..42
  end
end

então posso carregar apenas uma linha

dados=File.readlines("data.txt")
@product=Product.load_line dados[0]
@product.save
#<Product id: nil, code: "1", name: "PRODUTO 1", in_stock: false, date: "2008-11-21", price: 90.0>

ou carregar automáticamente todo arquivo em um array de Product

@products=Product.load_lines "data.txt"

conteúdo de @products

[
#<Product id: 29, code: "1", name: "PRODUTO 1", in_stock: true, date: "2008-11-21", price: 90.0>,
#<Product id: 30, code: "2", name: "PRODUTO 2", in_stock: false, date: "2008-11-22", price: 341.33>,
#<Product id: 31, code: "3", name: "PRODUTO 3", in_stock: false, date: "2008-11-01", price: 1.99>,
#<Product id: 32, code: "4", name: "PRODUTO 4", in_stock: true, date: "2008-11-15", price: 34.98>,
#<Product id: 33, code: "5", name: "PRODUTO 5", in_stock: false, date: "2008-11-14", price: 130.44>,
#<Product id: 34, code: "6", name: "PRODUTO 6", in_stock: true, date: "2008-11-05", price: 20.11>
]


Caso 2: Arquivos CSV

Utilizaremos o módulo ParseLine::CSV com o arquivo “data.csv”, a sintáxe é

  parse.field :nome_do_campo, lambda{|campo| fomatador}

para ignorar um campo como aquele “reservado para uso futuro” basta invocar o método ignore_field

Veja

class Product < ActiveRecord::Base
  extend ParseLine::CSV
  csv_layout :delimiter => ";" do |parse|
    parse.field :code
    parse.field :name
    parse.ignore_field
    parse.field :in_stock, lambda {|f| f == 'S' }
    parse.field :date ,    lambda {|d| d.split(/\//).reverse.join('-') }
    parse.field :price
  end
end

O ParseLine::CSV também tem os métodos Model.load_line e Model.load_lines.
Então temos para uma linha de dados

dados=File.readlines("data.csv")
@product=Product.load_line dados[0]
@product.save
#<Product id: nil, code: "1", name: "PRODUTO 1", in_stock: false, date: "2008-11-21", price: 90.0>

Ou carregar tudo de um array

@products=Product.load_lines "data.txt"


Instalação

#rubyforge
sudo gem install parseline

Se ainda não estiver disponível baixe aqui
Espero que gostem.

ps. em breve no GitHub em inglês

Novo tema

Monday, September 8th, 2008

Agora meu blog está com este novo tema; antes que alguem confunda, o Alexandro Lima me colocou como um monge, mas eu estou preparados para as piadinhas.

Limite por Tipo ou Aspecto

Tuesday, August 7th, 2007

A Ruby não faz distinção de elementos de um Array, o que eu acho uma vantagem fundamental, pois, a classe Array é uma classe para atender o escopo dos objetos remanescentes da linguagem. Como já conhecido por programadores em java, um array é de tamanho fixo e obedece a premissa que todos os elementos terão o mesmo tipo(considerando hierarquia). Em um aprendizado básico e inicial de uma linguagem de programação, a tipagem obrigatória é de fácil entendimento mas a coisa que contem coisas pode ou não aceitar tipos genéricos. Exemplo de uma mochila genérica no preposto abaixo

“Uma mochila onde aceita objetos menores que ela como, caneta, pendrive, laptop, absorvente, cueca, etc.”

Em uma tentativa de identificar o sexo do(a) dono(a) da mochila pelo seu conteúdo fica complicado pelo fato que ‘absorvente’ é usado por mulheres e ‘cueca’ por homens( normalmente é assim :).

Uma mochila genérica de um homem(deixa de ser genérica e passa a ser mochila-homem) não aceita ‘absorvente’ mas continua aceitando o catálogo de objetos masculinos. E outra coisa quando eu digo que a mochila ‘aceita objetos menores que ela’ também deixa de ser genérica e passa a ser limitada.

Limite por Tipo ou Aspecto

Em Java(a linguagem) as coleções tais como Vector e HashSet que antes da versão 1.5 recebiam apenas o tipo do topo da hierarquia ficando a critério do programador especificar em implementação de interfaces as conversões e verificação de tipo. Em uma proposta mais humana e menos burocrática o java 1.5 recebeu as definições de Generics tendo apenas a deficiência da dispersão das psedos-tags na declaração e na instância do objeto.

Array em Ruby o tipo não importa e também a linguagem não define uma limitação fixa da quantidade de elementos e as peculiaridades relativa a cada instância da coleção.

Considerando a linguagem na sua mais simples forma, a forma padrão sem APIs externas nenhuma das duas linguagens define uma coleção por aspecto.

Como seria este aspecto então?

Seria uma coleção capaz de determinar um contrato não burocrático sobre quais aspectos gostarias que a classe tenha. Algo como

“Aceite qualquer instância que siga a seguinte regra: tenha o método ’somar’ , criada na terça-feira, tenha a variável ‘hello’(string) com o conteúdo maior que 5″

Você deve estar pensando “Você tá ficando doido!!”… não, não é isso; isso é : Reduzir as condicionais para uso de elementos da coleção pense em “Coleções cuja as condicionais fiquem na entrada do elemento e não na saída”

De volta a pragmática…

Proponho aqui uma forma de criar um Array em Ruby que aceita apenas um tipo de classe, podemos estudar depois como fariamos algo utilizando os aspectos do objeto….

Módulo OnlyClass
Criei o módulo OnlyClass para facilitar o acoplamento na classe Array. Temos então a instância de um Array que aceita apenas um tipo de classe:

 colecao=Array.only String

O uso da classe é normal, há apenas verificação de inclusão dos elementos, neste caso String.

 colecao=Array.only String
 colecao << "Um elemento"   #ou
 colecao[1]="Dois elemento"  #ou
 colecao.push("Mais um elemento","Mais n elementos")

Veja que o array adiciona os elementos sem problema. Mas quando um elemento não for do tipo especificado uma exceção será lançada.

 colecao=Array.only String
 colecao << "esse vai"
 colecao << 333 #esse não
 #TypeError: can't append Fixnum into Array.only String

Módulo OnlyClass obtendo elementos e elementos dos métodos

Criei uma forma automática de obter os elementos de um método específico que já é comum a todas as instâncias pertencentes a coleção. Um exemplo seria obter os sucessores de todos elementos de um Array#Fixnum, chamando o each_nome-do-método-de-instância e um bloco(opcional)

 colecao=Array.only Fixnum
 colecao << 10
 colecao << 20
 colecao.push(30,40)
 colecao.each_succ {|n| puts n}
#resultado
# 11
# 21
# 31
# 41

sem o bloco, atribuição do resultado em uma variável

 colecao=Array.only Fixnum
 colecao << 10
 colecao << 20
 colecao.push(30,40)
 succs=colecao.each_succ              #=> [11, 21, 31, 41]

Podemos também passar parâmetros para o método, exemplo: obter todos os valores do resultado do match de cada elemento em um array.

 colecao=Array.only String
 colecao << "Um elemento"   #ou
 colecao[1]="Dois elemento"  #ou
 colecao.push("Mais um elemento","Mais n elementos")
 colecao.each_match(/.*u.*/) {|r| puts r}
#saída
# nil
# nil
# "Mais um elemento"
# nil

ou substituir os valores internos

 colecao=Array.only String
 colecao << "Um elemento"
 colecao[1]="Dois elemento"
 colecao.push("Mais um elemento","Mais n elementos")
 colecao.each_gsub!(/elemento/,'coisa')    #=> => ["Um coisa", "Dois coisa", "Mais um coisa", "Mais n coisas"]