Apresentação da versão 1.9 da Ruby
Web,ruby, Ajax ou qualquer outra coisa que me venha a cabeça (com prioridade para esta última)
24 fevereiro, 2008
Blueprint
Quando se constrói alguns sítios com HTML e CSS descobre-se que existem um conjunto de problemas semelhantes que temos que resolver em cada um deles. Entre estes problemas encontram-se: limpar os valores por omissão para uma série de propriedades dos vários navegadores de modo a podermos começar com uma página limpa; estabelecer a maqueta e a grelha base a que a nossa maqueta se vai conformar; criar valores de propriedades por omissão adequados para os tamanhos dos tipos, alinhamentos e espacejamento. E ainda mais algumas coisas. Seria realmente útil ter algo para fazermos isto à partida de modo a podermos fazer aquilo que os designers gostam.
Olav Bjorkoy pegou nesta ideia e tratou de a incorporar na infraestrutura BlueprintCSS, uma infraestrutura CSS, disponível publicamente que tenta alcançar estes objectos. Após o seu lançamento esta infraestrutura tem vindo a evoluir, criando extensões e adicionando características (nem sempre uma coisa boa). Qual é o impacto que uma coisa destas pode ter, na forma de trabalhar?
A infraestrutura Blueprint é uma infraestrutura de CSS acompanhada de algumas ferramentas externas que permitem validar, usando o validador de CSS do W3C (em java), os sítios criados e gerar grelhas alternativas, usando uma série de scripts em ruby, à grelha por omissão.
O que é que faz a Blueprint?
(aquilo que chamariamos em português a planta ou o projecto?)O conjunto central de características é o seguinte:
- Limpar os valores por omissão de propriedades de estilo dos navegadores;
- Estabelecer valores por omissão (noutros locais claro) adequados para tipografia incluindo famílias de tipos, tamanhos de cabeçalhos, estilos de parágrafos, estilos de listas, grelha base e ainda mais algumas coisas. Trata disto aplicando sempre valores relativos de modo a poder ser escalado em qualquer navegador;
- Dá-nos uma metodologia a usar em grelhas de maqueta à medida. Qualquer número de colunas e larguras com que possa sonhar ficam fáceis de alcançar;
- Oferece uma folha de estilo para impressora adequada;
- Faz tudo isto de forma elegante na generalidade dos navegadores que o podem visitar, incluindo o IE6 e IE7.
É importante compreender que todos os elementos podem ser sobrepostos. A Blueprint não foi concebida para ser a folha de estilo única para um sítio. É, pelo contrário, um conjunto de estilos base para que o designer possa construir sobre alicerces sólidos, aplicando o que é adequado e sobrepondo-se aquilo que não lhe serve para o caso em mãos.
Por analogia podemos pensar que conceber um site com CSS é como começar com baldes de argamassa e conceber um sítio usando a Blueprint é conceber algo usando blocos mas tendo ainda acesso à argamassa.
A grelha
O cerne da Blueprint são as ferramentas de construção de grelha. Por omissão o ficheiro grid.css (um dos ficheiros da infraestrutura) estabelece uma grelha com uma largura de 950px (quase os 960px recomendados pelo Cameron) com 24 colunas, cada uma com 30px de largura com 10px de esquadria. Esta grelha será normalmente suficiente para a generalidade das necessidades.
Para as excepções é possível mudar isto à medida. Se necessitar de mais ou menos colunas ou que sejam mais largas ou mais estreitas que estejam mais apertadas ou mais separadas pode usar a ferramenta de geração de grelha CSS da Blueprint. Pode ainda usar o ficheiro compress.rb como abaixo indicado. O gerador de blueprint não só oferece um ficheiro grid.css de substituição como cria um ficheiro de imagem grid.png para uso como imagem de fundo durante o desenvolvimento, algo que nos permite assegurar um alinhamento perfeito. O gerador de grelha é uma peça central da infraestrutura, mesmo que tecnicamente seja uma ferramenta exterior. Sem ela a Blueprint seria limitativa e controladora, forçando os designers a usar uma só grelha de maqueta. Com ela os designers têm liberdade total.
Usar a Blueprint na sua cadeia de trabalho
Antes de começar a usar o Gimp (ou ferramenta equivalente) deve começar a planear com o Blueprint. É contudo possível, mas mais complicado fazer o caminho inverso.
O designer pode usar a ferramenta de geração acima mencionada de modo a criar uma maqueta com o número de colunas exacto, com esquadrias adequadas e uma largura total adequada ao projecto concreto. O designer deve guardar o ficheiro grid.css exportado. Pode então criar um documento gimp que reproduza esta estrutura em colunas.
O designer no final deve passar, à pessoa que fica encarregue de traduzir a imagem composta no Gimp para CSS e HTML, o ficheiro grid.css acima mencionado e deve dar a conhecer ainda as guias na composição gráfica.
Quando se usa a Blueprint, é realmente importante ler todas as regras incluídas no CSS e compreender as mesmas completamente, de modo a ficar-se consciente do que faz e como o faz antes de deitar a mão na massa. Se o não fizer podem escapar-lhe coisas importantes como .border, .colborder, .box e .hide.
Não seja enganado pela recomendação da documentação de grid.css que lhe sugere usar elementos div para todas as colunas. Pode aplicar a classe .column a qualquer elemento. Por exemplo, se estiver a usar a grelha por omissão e quizer uma barra no topo da página que inclua um logótipo do lado esquerdo e a navegação do lado direito pode adicionar class="column span-12" a um elemento h1 e a um elemento a ul em vez de criar div desnecessárias.
Para criar «linhas» na sua maqueta use várias div com a classe .container. O seu cabeçalho pode ser um contentor, o seu conteúdo outro e o seu rodapé ainda outro. Pode claro ter muitos mais. Só não pense que só pode usar um contentor.
Lembre-se ainda que não necessita de usar a totalidade das peças da Blueprint. Se por exemplo não estiver a usar uma maqueta baseada numa grelha não necessita de usar grid.css. Contudo reset.css e typography.css podem ainda ser-lhe úteis.
Finalmente. Nunca altere os próprios ficheiros Blueprint! É mais limpo incluir as suas próprias folhas de estilo e sobrepôr-se às regras da Blueprint. A alteração dos ficheiros CSS da Blueprint tornam mais difícil a actualização para a última versão da infraestrutura.
Instalação
A Blueprint deve ser colocada na pasta de CSS do sítio em que é aplicada. Depois de o fazer pode adicionar as 3 linhas seguintes ao elemento <head>:
<link rel="stylesheet" href="css/blueprint/screen.css" type="text/css" media="screen, projection">
<link rel="stylesheet" href="css/blueprint/print.css" type="text/css" media="print">
<!--[if IE]><link rel="stylesheet" href="css/blueprint/ie.css" type="text/css" media="screen, projection"><![endif]-->
Se estiver a trabalhar em xhtml não esquecer de terminar cada uma das linhas com um />
Estes ficheiros encontram-se na pasta de raiz de Blueprint. Sendo as versões compactadas.
A Blueprint está pronta a ser usada.
Pasta 'src'
- blueprint/src/reset.css: é o ficheiro que trata de limpar os valores CSS que os navegadores assumem por omissão;
- blueprint/src/grid.css: Este ficheiro estabelece a grelha. Inclui várias classes que aplicadas a div (às várias div) criam uma grelha baseada em colunas;
- blueprint/src/typography.css: Este ficheiro estabelece tipografia por omissão. Inclui ainda alguns métodos para brincar com o seu texto;
- blueprint/src/forms.css: Estabelece estilo minimalistas para formulários;
- blueprint/src/print.css: Estabelece regras para impressão, de modo a que o seu sítio seja impresso com estilo. Deve ser incluído em cada página;
- blueprint/src/ie.css: Inclui o lixo exigido pelos amados IE6 e IE7.
Pasta 'lib'
- blueprint/lib/compress.rb: Um script em Ruby para alterar à medida e comprimir o seu CSS. Pode estabelecer um espaço de nomeação, o número de colunas (pode ser usado em alternativa ao gerador acima indicado), larguras, trajectos de saída de ficheiros, vários projectos e nomes de classes semânticas. Ver os comentários em compress.rb ou executar compress.rb -h para informação adicional;
- blueprint/lib/validate.rb: Valida os ficheiros centrais da Blueprint usando o validador CSS do W3C;
- blueprint/lib/settings.example.yml: Um ficheiro de exemplo para quem necessite de indicar valores à medida.
Pasta 'tests'
Inclui ficheiros html para testar a maior parte dos aspectos da Blueprint. Para mais instruções ver tests/index.html
Finalmente uma cábula [pdf] para o blueprint.
17 agosto, 2007
Preguiçoso ou Trabalhador
class Empregado
def emails
@emails ||= []
end
end
ou
class Empregado
def initialize
@emails = []
end
end
A motivação para passar a iniciar cedo atributos (ser trabalhador) é a da legibilidade do código. A mudança de valor de atributos inicados tardiamente, à lá Calvin (ver imagem não é a que queria mas não tenho scanner para a que quero e não estou para ir procurar), ocorre no seu acesso. Os atributos iniciados tardiamente podem ser problemáticos para depurar porque o seu valor muda quando se lhes acede. Os atributos iniciados cedo iniciam os seus atributos no construtor da classe.
27 julho, 2007
ruby-lang pt
Ontem estive à noite com o Joaquim, a sua namorada, o Francisco, o Pedro, e o João no Peters para o lançamento da versão portuguesa do sítio da ruby. Aquilo foi um mero evento social. Nele falou-se de tudo um pouco e a certa altura derivou-se para a forma como se gasta dinheiro, como há mesmo algum novo riquismo na forma de o gastar (Ver conta geral do estado).
Mesmo com esse nível de gastos podemos continuar a encontrar sítios como este: O sítio do Ministério da Cultura mostra o lado oposto uma pobreza franciscana (nenhuma referência ao Francisco) nos seus código e conteúdos.
Parece que o sítio foi concebido por um imberbe em desenvolvimento de sítios web, talvez até esteja a criticar a pessoa errada. Talvez me esteja a equivocar e a acusar o trolha de não saber de electricidade (como o da manutenção do semáforo).
Tenho que admitir que não esperava ver código com <font... ou <b num sítio oficial. Claro está que isto é um sítio com tabelas para tratar de arranjos.
Além da pobreza do código, a pobreza dos conteúdos é fantástica. Por exemplo fui ver a agenda, hoje 27 de Julho apresentam como destaques dança, música, exposições e teatro. Na dança destacam algo sucedido em 21 de Julho, algo que já não pode ser apreciado ao vivo. Tudo bem, será que tinham algo sobre as reacções do público ao espectáculo, não, isso seria demais.
Fico parvo quando veja que o estado gasta uma pipa de massa a auditar sítios oficiais, ou a tarefa encomendada aos auditores é algo que não gera alterações ou estão a auditar algo errado ou a própria auditoria enferma de defeitos ou uma combinação disto, não sei.
Acho que um dia destes crio um pastiche do site só para experimentar. Não parece muito difícil. O único problema é que aquilo parece tudo reles, uns botões animados que já ficavam mal em 1999.
23 julho, 2007
Rake - Um Ajudante da Automatização das Tarefas
Necessita de automação? Use Rake ou Sake!
Para quem não conheça o Rake é uma linguagem de domínio específico escrita em Ruby.
Neste artigo vou introduzir a rake e descrever algumas pistas para automatização de tarefas repetitivas que se fazem no dia a dia.
Teoria
A Rake foi desenvolvida por Jim Weirich e baseia-se em Ruby, o que quer dizer que temos acesso completo às capacidades da Ruby de dentro da Rake. A Rake não está limitada aquilo que conhece em ferramentas similares é muito mais poderosa e flexível (isto é aliás um sinal de perigo).
A Rake funciona à base de dependências. Quando se escreve um guião Rake iremos dizer-lhe que uma dada tarefa depende de outra e assim sucessivamente. Deste modo podemos construir uma receita completa para explicar como fazer as coisas e a respectiva ordem de execução.
Como a Rake é construída em Ruby podemos fazer o que quisermos nas suas tarefas:
- manipular ficheiros
- compilar os nossos programas
- limpar o nosso (do computador claro) sistema de ficheiros
- gerar esqueletos de aplicações
- e ainda muito mais
Primeira Tentativa: Adicionar uma tarefa e fazer com que seja executada por omissão
task :default => [:ola]
desc "Esta é a nossa primeira tarefa"
task :ola do
puts "Olá! Sou a primeira tarefa escrita por nós!"
end
desc "Execução de Teste"
task :test do
require 'rake/runtest'
Rake.run_tests 'tests/*.rb'
end
Na primeira linha dizemos ao rake que a nossa tarefa por omissão, a que é chamada quando usamos rake na linha de comando sem aditivos será a tarefa designada por ola. Pode ainda tentar chamar-se explicitamente essa tarefa usando o comando rake ola
Depois na linha seguinte descrevemos a tarefa que vamos executar. Esta descrição irá ser impressa quando usamos o comando rake -T para ficarmos a saber quais as tarefas disponíveis no nosso Rakefile.
Finalmente definimos a nova tarefa ola usando a palavra chave task. Aquilo que colocamos dentro da tarefa é código Ruby perfeitamente normal.
A Rake oferece algumas capacidades de manipulação de ficheiros, criação de gemas e coisas que tais. Deve ler a sua API para mais informação.
Usamos essas capacidades para a tarefa testes ao carregar a biblioteca distribuida com a Rake e chamando um desses métodos. Por exemplo estamos a carregar a biblioteca runtest e executar cada ficheiro de teste que se encontre na pasta de "tests".
Encadear tarefas
task :carregar_ficheiros do
# fazer o carregamento
end
task :ligacaossimbolicas => :carregar_ficheiros do
# criar ligações simbólicas do lado do servidor
end
task :instalar => :ligacaossimbolicas do
# instalar a última revisão do nosso projecto
end
Agora temos uma série de tarefas que podemos usar. Se escrevermos rake instalar, essa tarefa irá chamar a tarefa ligacoessimbolicas que depende da tarefa carregar_ficheiros. Assim a Rake irá executar a tarefa carregar_ficheiros em primeiro lugar, depois a tarefa ligacoessimbolicas e depois instalar.
É assim que pode encadear tarefas e assegurar-se que todos os passos exigidos são executados antes de executar o que está a pedir ao Rake.
Conclusão
Se começar a usar Rake para automatizar as suas tarefas rapidamente compreenderá que é uma ferramenta poderosa e fácil de usar. Uma das coisas mais interessantes é que a Rake foi construída em Ruby e que Ruby pode correr em qualquer sistema operativo. Claro que saber Ruby irá ajudar a aprender realmente a usar a Rake e a escrever a suas próprias tarefas simples mesmo que seja s o um principiante em Ruby.
A Rake não é só para utilizadores de Ruby, pode ser usada para montar programas em C, limpar o sistema de ficheiros, instalações, administração das suas bases de dados, ...
05 junho, 2007
Método para determinação de OS em Ruby
def platforma
$RUBY_PLATFORM ||=
case RUBY_PLATFORM.downcase
when /linux|bsd|solaris|hpux|darwin/
:unix
when /mswin32|mingw32|bccwin32/
:windows
when /cygwin/
:cygwin
when /java/
:java
else
:outra
end
end
p platforma
03 junho, 2007
Hackety hack
Hackety hack é um projecto de Why the lucky stiff para se poder aprender a programar (já agora em ruby). Na primeira lição vamos descobrindo como programar. Como interagir com o utilizador (para lhe pedir algo e para lhe indicar algo). O sumário da lição é apresentado no seu final.
Na primeira lição aprende-se o seguinte:
- Comandos fazem coisas tal como os cães fazem coisas;
- Variáveis guardamcoisas;
- Cria-se uma variável com um sinal de igual. É assim que a Ruby sabe -- através desse sinal de igual!
- Os comandos pertencem à coisa do lado esquerdo do ponto;
- Os comandos comem coisas entre parêntesis como se fossem biscoitos;
09 maio, 2007
As diferenças entre =, ==, equal? e eql?
Em ruby um sinal de igual (=) significa que se atribui à identificação da esquerda o que está à direita.
saudacao1 = "Viva Catarina."
saudacao2 = "Adeus."
saudacao3 = "Viva Catarina."
Se quisermos perguntar se o conteúdo de saudacao1 é igual ou não a saudação3 exprimimos tal usando a segunda expressão == (dois sinais de igual como sucede com várias outras linguagens de programação). Neste caso o valor devolvido é verdade. Se usarmos a expressão equals? aquilo que estamos a perguntar é se duas referências para objectos apontam para o mesmo objecto (não se esqueçam que em ruby tudo é um objecto), o que no caso de saudacao1 e saudacao3 é falso. Finalmente eql? responderá verdade pois compara valores.
07 maio, 2007
Soluções simples
Por vezes as soluções mais simples são as mais apropriadas. Recentemente na lista de correio comp.lang.ruby surgiu algumém a perguntar se havia um modo de passar o nome equivalente de um modelo (exemplo: tenho um modelo designado por dept_alimentar e desejo passar a string "dept_alimentar" e depois converte-lo (ou molda-lo [cast]) no modelo original equivalente e assim posso usar o seu objecto no método chamado, estou a tentar fazer isto pois quero evitar passar um objecto o que se tornará muito pesado).
David Chelimsky respondeu no seu tom extra humilde (que caso não estivesse a entender a questão o que sucede com frequência) é que quando se passa o dept_alimentar ou DeptAlimentar para outro método, não há a passagem do objecto propriamente dita mas sim a de uma variável que detem uma referência para o objecto. O que é sugerido de facto torna-se mais caro tem termos de cálculo do que usar uma variável.
31 março, 2007
Uma pequena experiência
Por vezes é necessário experimentar para perceber o que determinada coisa pode fazer por exemplo numa das listas de correio da ruby aparecia a seguinte questão, o que é que quereria dizer algo como isto: puts gets gets (já agora na versão actual deve receber uma mensagem de aviso no caso de estas estarem activadas). Bom a melhor forma de saber o que isto quer dizer é fazer uma pequena experiência:
irb(main):001:0> puts(interior=gets(exterior=gets))
PARA
O Texto interior e este
PARA
O Texto interior e este
PARA
=> nil
irb(main):002:0> p interior
"O Texto interior e este\nPARA\n"
=> nil
irb(main):003:0> p exterior
"PARA\n"
=> nil
irb(main):004:0>
10 janeiro, 2007
Variáveis de instância de classe - Ruby
Isto é uma tradução de um artigo de Martin Fowler sobre ClassInstanceVariable (uma variável de instância de classe).
Quando se aprende algo sobre objectos normalmente aprendemos que esses objectos capturam dois tipos de dados: instância (exemplar) e classe. As variáveis de instância são as mais comuns, os dados variam de instância para instância do objecto. As variáveis de classe, também conhecidas por variávies estáticas, são partilhadas por todas as instâncias (exemplares) da classe. Cada instância aponta para o mesmo valor e qualquer alteração é vista por todas as instâncias. As variáveis de classe são muito menos comuns do que as variáveis de instância especialmente variáveis de classe que sejam mutáveis.
Um dos aspectos complexos das variáveis de classe é como é que elas interagem com uma hierárquia de herança. Consideremos uma variável de classe que é usada para guardar a própria instância.
class Empregado@@exemplares = []def self.exemplaresreturn @@exemplaresenddef guardar@@exemplares << selfenddef initialize nome@nome = nomeendendEmpregado.new("Martins").guardarEmpregado.new("Roberta").guardarEmpregado.new("Eurico").guardarputs Empregado.exemplares.size
Não há aqui nenhuma surpresa, há três empregados. Agora experimentemos isto:
class Empregado@@exemplares = []def self.exemplares@@exemplaresenddef guardar@@exemplares << selfenddef initialize nome@nome = nomeendendclass Programador < Empregado; endclass Restodopessoal < Empregado; endRestodopessoal.new('Martins').guardarRestodopessoal.new('Roberta').guardarProgramador.new('Eurico').guardarputs Restodopessoal.exemplares.sizeputs Programador.exemplares.size
O resultado é 3 e 3, enquanto preferiamos obter 2 e 1. A razão por que isto se passa é que a variável de classe é partilhada ao longo de todas as instâncias da classe e essas incluem todas as subclasses. Há duas classes mas só uma variável.
Por vezes esta variável que perpassa a totalidade da hieráquia é o que necessitamos, mas por vezes, como neste caso, preferiamos ter uma variável diferente em cada classe. Podemo-nos referir a uma variável de instância de classe do mesmo modo que a uma variável de classe, mas teremos um valor diferente por classe.
O suporte para variáveis de instâncias de classe não é comum nas linguagens OO, mas não é difícil de criarmos um nós próprios. O modo óbvio de o criar seria o de usar um dicionários de chaves por nome de classe.
class Empregado@@exemplares = {}def self.exemplares@@exemplares[self]enddef guardar@@exemplares[self.class] || = []@@exemplares[self.class] || = << selfenddef initialize nome@nome = nomeendendclass Programador < Empregado; endclass Restodopessoal < Empregado; endRestodopessoal.new('Martins').guardarRestodopessoal.new('Roberta').guardarProgramador.new('Eurico').guardarputs Restodopessoal.exemplares.sizeputs Programador.exemplares.size
Pode usar esta técnica em qualquer linguagem OO. Ruby contudo tem de facto variáveis de instância de classe.
class Empregadoclass << self; attr_accessor :exemplares; enddef guardarself.class.exemplares || = []self.class.exemplares << selfenddef initialize nome@nome = nomeendendclass Programador < Empregado; endclass Restodopessoal < Empregado; endRestodopessoal.new('Martins').guardarRestodopessoal.new('Roberta').guardarProgramador.new('Eurico').guardarputs Restodopessoal.exemplares.sizeputs Programador.exemplares.size
A definição da variável de instância de classe é o fragmento class << self; attr_accessor :exemplares; end.