21Abr08 Histórico da linha de comando

Seguindo o post do Luke Franci:

$ history 1000 | awk '{a[$2]++}END{for(i in a){print a[i] " " i}}' | sort -rn | head
110 vi
65 rake
43 gcc
40 ls
40 cd
24 rm
24 ./mc
18 thin
18 svn
15 su

Faça o teste e poste nos comentários ou em seu blog!

tags {, }

13Abr08 Suporte a TimeZone no Rails 2.1: uma visão geral

Esta é uma tradução do artigo escrito por Geoff Buesing.

Este será o primeiro de muitos posts que farei sobre os novos recursos de time zone (fuso horário) na próxima versão (2.1) do Rails. Neste post, eu darei uma visão geral destes novos recuros, na criação de um novo aplicativo.

Começarei com um aplicativo Rails 2.1 criado através do comando “rails”. No 2.1, suporte a fuso horário estará ligado por padrão no environment.rb, através da opção config.time_zone:

# config/environment.rb
config.time_zone = 'UTC'

– Este estará definido para UTC como padrão, mas você irá normalmente modificar isto para um fuso horário apropriado para sua localidade. As novas tarefas do rake time:zones:all, time:zones:us, e time:zones:local foram adicionadas para ajudá-lo a encontrar os nomes adequados de fuso horário. time:zones:local farão uma tentativa educada baseada no sistema local de horário, então este é um bom lugar para se começar:

$ rake time:zones:local
* UTC -06:00 *
Central America
Central Time (US & Canada)
Guadalajara
Mexico City
Monterrey
Saskatchewan

Carlos: este é o exemplo usado no artigo original, não vou modificar pois os exemplos se baseam nestes resultados…. no meu sistema acontece isso:

$ rake time:zones:local
* UTC -02:00 *
Mid-Atlantic

Para este exemplo, eu usarei config.time_zone para US Central Time:

# config/environment.rb
config.time_zone = 'Central Time (US & Canada)'

A seguir, criarei um simples scaffold para um modelo Task, com um atributo datetime alert_at:

$ script/generate scaffold Task name:string alert_at:datetime
$ rake db:migrate
$ script/server

Irei ao formulário para nova tarefa, e criarei uma:

new_task1.png

A action show exibe a data e hora que eu digitei, seguido pela correção (deslocamento) UTC:

show_task1.png

… para este exemplo, o prefixo UTC é -0500, que é a correção para US Central Time durante o “horário de verão”:

Para mostrar como este horário é guardado no banco de dados, eu vou ao script/console, e usar o método #alert_at_before_type_cast:

>> t = Task.find_by_name('foo')
=> #< Task … >
>> t.alert_at
=> Sun, 06 Apr 2008 10:30:00 CDT -05:00
>> t.alert_at_before_type_cast
=> "2008-04-06 15:30:00"

O banco de dados está guardando a representação UTC de nosso horário: 15:30 UTC é simultâneamente 10:30 CDT (Central Daylight Time - daylight é o horário de verão). A diferença entre os dois horários é a correção UTC (-5 horas, neste caso).

Depois, eu vou editar a tarefa e alterar o mês para Janeiro (fora do horário de verão, lá):

edit_task.png

Note que a correção UTC agora é -0600 - por que o alert_at não está mais no horário de verão.

show_task_updated.png

script/console confirmará que o banco de dados recebeu a representação correta UTC:

>> t = Task.find_by_name('foo')
=> #< Task … >
>> t.alert_at
=> Sun, 06 Jan 2008 10:30:00 CST -06:00
>> t.alert_at_before_type_cast
=> "2008-01-06 16:30:00"

A hora do banco de dados é agora 16:30 ao invés de 15:30, por que a correção UTC é -6 horas agora.

Fusos por usuário

O que eu defini anteriormente funcionará bem para um aplicativo onde todos os usuários estão no mesmo fuso. Se o aplicativo eventualmente necessitar suportar usuários em fusos diferentes, é bastante fácil de se fazer isso:

Primeiramente, eu criarei um scaffold de usuário, com um atributo string para guardar o fuso do usuário:

$ script/generate scaffold User name:string time_zone:string
$ rake db:migrate

Mudarei formulário do usuário para usar o combo de fusos ao invés de um campo de texto:

# views/users/new.html.erb
<%= f.time_zone_select :time_zone, TimeZone.us_zones %>

O novo formulário de usuário ficará assim — eu o usarei para criar alguns usuários com fusos diferentes:

new_user.png

Para efeitos de demonstração, eu adicionarei um before_filter simples chamado “login_from_querystring” ao ApplicationController:

# controllers/application.rb
before_filter :login_from_querystring
def login_from_querystring
  @current_user = User.find_by_name(params[:user])
end

Então adicionarei um outro before_filter “set_time_zone”, que definirá o Time.zone para o fuso do usuário atual:

# controllers/application.rb
before_filter :set_time_zone
def set_time_zone
  Time.zone = @current_user.time_zone if @current_user
end

Adicionarei um cabeçalho ao layout para mostrar quem está logado, seu fuso horário e o hora atual em seu fuso horário:

# views/layouts/tasks.html.erbCurrent user: <%= @current_user.name if @current_user %>
Current time zone: <%= Time.zone.name %>
Current time: <%= Time.zone.now.inspect %>
<hr />

Finalmente, modificarei a view da index das tarefas para usar a representação #inspect do alert_at, para nos revelar alguns detalhes adicionais:

# views/tasks/index.html.erb
<%=h task.alert_at.inspect %>

Agora, se eu logar com um dos usuários que eu criei, eu verei a tarefa que criei anteriormente, com o alert_at ajustado para o fuso do usuário atual:

index_usuario1.png

… note que o horário exibido para a tarefa é 11:30 EST - que é o mesmo que 10:30 CST.

Para o usuário em US Mountain Time, a tarefa será mostrada como 9:30 MST:

index_usuario2.png

Sem um usuário logado, o fuso usado é o definido em config.time_zone:

index_usuario21.png

Métodos para criar horários no Time.zone atual

Anteriormente, nós estávamos nos apoiando no ActiveRecord para automaticamente converter atributos do model para o horário local do usuário. Para casos onde você precisa criar novas instâncias de Time no fuso local do usuário, os métodos Time.zone.local(), Time.zone.parse() e Time.zone.now() estão disponíveis, assim como Time.zone.now():

>> Time.zone = 'Hawaii'
=> "Hawaii"
>> Time.zone.now
=> Wed, 09 Apr 2008 15:48:18 HST -10:00
>> Time.zone.local(2008, 4, 9, 15, 48, 18)
=> Wed, 09 Apr 2008 15:48:18 HST -10:00
>> Time.zone.parse('2008-04-09 15:48:18')
=> Wed, 09 Apr 2008 15:48:18 HST -10:00
>> Time.zone.at(1207792098)
=> Wed, 09 Apr 2008 15:48:18 HST -10:00

Time e DateTime #in_time_zone converterá qualquer instância para o fuso em Time.zone:

>> Time.zone = 'Alaska'
=> "Alaska"
>> t = Time.utc(2000)
=> Sat Jan 01 00:00:00 UTC 2000
>> t.in_time_zone
=> Fri, 31 Dec 1999 15:00:00 AKST -09:00

… ou, para qualquer fuso ou identificador de fuso (ex.: nome, inteiro ou Duration):

>> t.in_time_zone('Hawaii')
=> Fri, 31 Dec 1999 14:00:00 HST -10:00
>> t.in_time_zone(-6.hours)
=> Fri, 31 Dec 1999 18:00:00 CST -06:00

Dica: Atualizando seu aplicativo

  1. o novo recurso de fuso horário assume que seu banco de dados está guardando horários em UTC, então se você está atualmente guardando horários em um fuso diferente de UTC, você precisará migrar os dados existentes para UTC.
  2. se você instalou o plugin tzinfo_timezone, você precisará removê-lo, dado que este sobrescreve a classe TimeZone no ActiveSupport.
  3. a gem TZInfo não é mais necessárioa, dado que esta está agora dentro do ActiveSupport. De toda forma, se você tem uma versão recente desta gem instalada, Rails favorecerá a gem sobre a versão incluída no ActiveSupport.
  4. A versão do TZInfo incluída no ActiveSupport é uma versão compacta da gem, então se você está interagindo com a API do TZInfo diretamente, você precisará da gem instalada.
  5. Se você não deseja usar o novo recurso de fuso horário - este novo recurso não deve interferir em seu código existente, desde que você não declare o config.time_zone em seu environment.rb.

No próximo capítulo…

Nos próximos posts, tentarei cobrir mais coisas “escondidas”, mas esperamos que este post ajude vocês

Se você acha fuso horário, correções UTC, e horário de verão confuso, você talvez queira ver estas validações de fuso horário, que talvez te deixem ainda mais confuso…

tags {, , }

9Abr08 Telefone

Acredito que muitos de vocês não perceberam - no nosso contato ou rodapé -, mas o nosso telefone mudou. Agora é +55 31 3227 1009. Vocês que são os nossos amigos, clientes e parceiros vão ter muito mais facilidade para entrar em contato conosco.

Antes nós usávamos o serviço SkypeIn da Skype, que é muito bom e simples. O problema é que dependíamos dos computadores, internet e fone-microfone para atender e sempre acontecia algum problema. Agora, para não dar mais brecha pro Murphy, resolvemos assinar uma linha de telefone convencional.

Agora todos poderão entrar em contato com a Milk-it com mais comodidade e sem uma secretária eletrônica falando em inglês. :D

tags {}

1Abr08 Mudanças…

Há algum tempo estávamos cogitando mudar a nossa forma de trabalho e nossas tecnologias, então venho informar que não vamos mais trabalhar com Ruby on Rails, GNU/Linux e boa parte das soluções livres. Isso se deve ao fato das soluções da Microsoft atenderem muito melhor a nossa empresa. Agora todas as nossas estações de trabalho serão Windows XP com Office 2007 e Visual Studio 2008, todas as licenças já estão em posse da Milk-it.

Agradecemos a toda a comunidade software livre, especialmente a Ruby on Rails e Gentoo, mas atualmente as soluções da Microsoft nos atendem muito melhor. Como todos os nossos projetos abertos usam tecnologias livres, vamos fechar o nosso repositório svn.milk-it.net/open pelo simples fato de não fazer mais sentido dar manutenção neles.

Sei que muitos de vocês lêem o nosso blog por conta dos posts voltados para software livre, mas espero a compreensão de todos.

tags {, , }

10Mar08 Processamento de imagens com Qt

Este semestre estou cursando uma matéria que se chama Processamento de Imagens Digitais na PUC-MG e, diga-se de passagem, estou gostando muito da matéria. Recebemos então nosso primeiro trabalho prático que consiste em 3 passos, sendo o que primeiro irá gerar a versão em escala de cinza de uma imagem. Considerei esta a oportunidade perfeita para aprender a trabalhar com Qt.

Como o trabalho necessitava de uma interface gráfica (exigência do professor), comecei com o Qt Designer. O programa é realmente muito bom e fácil de mexer! Por usar caixas de ferramentas flutuantes, recomendo o uso de uma área de trabalho somente para o programa.

O segundo passo foi escrever o comportamento da interface, ou melhor, o trabalho de fato. Como este não é um tutorial de Qt vou pular direto para a manipulação da imagem. Escrevi então o seguinte código para deixar a imagem em escala de cinza utilizando a QImage:

void
pidMain::generateGrayScale()
{
    // ocultei o código original pois se trata de recuperar o objeto QImage e nada mais
    QImage *original = getImage();
    QImage *gray = new QImage(original->width(), original->height(), QImage::Format_RGB32);
    QRgb grayPix;
    QColor *curPix;
    int bright;    

    for (int i =0; i < gray->width(); i++)
        for (int j = 0; j < gray->height(); j++)
        {
            curPix= &QColor::fromRgba(original->pixel(i, j));
            bright = qRound(0.3 * curPix->red() + 0.5 * curPix->green() + 0.2 * curPix->blue());
            grayPix = qRgb(bright, bright, bright);
            gray->setPixel(i, j, grayPix);
        }    

    // também ocultei o código original aqui. Agora temos uma imagem em escala de cinza no ponteiro "gray"
}

Espero que este código seja útil a alguém ! Caso queiram opinar, melhorar, estragar ou qualquer coisa, o código para alteração está aqui !

Abraços!

tags {, , }