Cairo Noleto

Notícias sobre PHPUnit

| Comments

No dia 20/10 foi lançado a versão 3.3.2 desse framework de testes.

Foram adicionados algumas funcionalidades e corrigidas vários bugs. Quem já tem instalado o PHPUnit sobre o pear, apenas faça o upgrade

sudo pear upgrade phpunit/PHPUnit

Que ganhar um ingresso para o PHP Conference?

| Comments

Quer ganhar?! Então faz o seguinte:

Escreve uma frase bem legal sobre o que você ai encontrar lá, imagina aí um milhão de coisas :P

As duas melhores frases vão ganhar um ingresso para curtir o PHP Conference junto com a galera da Add4 Comunicação!!

Então não vacila, da uma olhada aqui e tenha mais detalhes sobre essa promoção :D

Create, update, destroy e index não são obrigatórios!

| Comments

Olá, mas que titulo é esse? O que quer dizer isso!?

Eu acompanho e muito a comunidade RubyOnRails brasileira, e tenho notado um comportamento que vem tomando conta principalmente nos novatos, que é o de querer a obrigatoriedade dos métodos index, create, update e destroy.

Como todos sabemos, temos que adicionar, remover e atualizar nossos dados, em alguns casos específicos listar todos os dados, mas isso não é obrigatório, bem como o nome desses métodos não são obrigatórios!

Ao invés de utilizar o método index para listar, posso utilizar o método show_all para mostrar todos algo como users/show_all.

Eu acho que esse comportamento está derivando do mal uso do scaffold. Para quem ainda não entendeu, scaffold é para gerar uma estrutura INICIAL para seus clientes alimentarem os dados de seus sistemas. Não é para ser usado como a roda que gira o mundo ou como “The golden bullet”. O scaffold deve ser usado em casos especificos, geralmente usados no inicio do desenvolvimento em apoio para os desenvolvedores lidarem com dados reais da aplicação ou quando a demanda de dados do cliente não pode parar.

Não usem scaffold para se gabar a seus amigos:

“Duas linhas de código e já estava pronto” ou “Que ver eu fazer um blog em 15 minutos?!”

Usem com consciência:

“Maria, aqui está o formulário inicial para entrada dos dados relativo a nova categoria de imóveis, até o final do dia de amanhã eu irei te mostrar como a tela realmente irá funcionar, enquanto não fica finalizado, você já pode começar a trabalhar”.

Tradução: Rails database Migrations - Parte II

| Comments

Esta é a segunda parte da tradução do artigo Rails database Migrations. Mais uma vez, antes de desfrutarem da leitura, quero dizer-lhes que se encontrar erros de português ou a tradução com sentido diferente, por favor, comuniquem-me! Avisem-me por email, twitter (caironoleto), ou qualquer mensageiro!! :P

2.0 Criando migrações

2.1 Criando um Modelo

Um Modelo e os geradores de scaffold criará migrações apropriadas para criação de um novo Modelo. Esta migração contém instruções prontas para criação de uma tabela relevante. Se você mostrar pro Rails as colunas que você precisa então as declarações já estarão criadas. Por exemplo, rodando ruby script/generate model Product name:string description:text gerará uma migração como esta

1
2
3
4
5
6
7
8
9
10
11
12
13
class CreateProducts < ActiveRecord::Migration
  def self.up
    create_table :products do |t|
      t.string :name
      t.text :description
      t.timestamps
    end
  end

  def self.down
    drop_table :products
  end
end

Você pode adicionar quantos nomes/tipo de colunas como você deseja. Por padrão t.timestamps (Que criam as colunas updated_at e created_at que serão populadas automáticamentes pelo Rails) podem ser adicionadas para você.

2.2 Criando uma migração autônoma

Se você criar uma migração para outros propósitos (Por exemplo, adicionar uma coluna numa tabela já existente) então você pode usar o gerador de migrações:

ruby script/generate migration AddPartNumberToProducts

Criará uma migração vazia mas já apropriada com o nome da migração:

1
2
3
4
5
6
7
8
class AddPartNumberToProducts < ActiveRecord::Migration

  def self.up
  end

  def self.down
  end
end

Se o nome da migração é na forma AddXXXtoYYY ou RemoveXXXtoYYY e for seguida de uma lista de nomes de colunas e seus tipos então a migração será criada contendo declarações apropriadas para adicionar e remover colunas.

ruby script/generate migration AddPartNumberToProducts part_number:string

Gerará:

1
2
3
4
5
6
7
8
9
class AddPartNumberToProducts < ActiveRecord::Migration
  def self.up
    add_column :products, :part_number, :string
  end

  def self.down
    remove_column :products, :part_number
  end
end

Similarmente:

ruby script/generate migration RemovePartNumberFromProducts part_number:string

gerará

1
2
3
4
5
6
7
8
9
class RemovePartNumberFromProducts < ActiveRecord::Migration
  def self.up
    remove_column :products, :part_number
  end

  def self.down
    add_column :products, :part_number, :string
  end
end

E você não está limitado a gerar magicamente apenas uma coluna, por exemplo

ruby script/generate migration AddDetailsToProducts part_number:string price:decimal

gerará

1
2
3
4
5
6
7
8
9
10
11
class AddDetailsToProducts < ActiveRecord::Migration
  def self.up
    add_column :products, :part_number, :string
    add_column :products, :price, :decimal
  end

  def self.down
    remove_column :products, :price
    remove_column :products, :part_number
  end
end

E sempre o que foi gerado é apenas um ponto de partida, você pode adicionar ou remover a partir dele o que você quiser, como você achar melhor.

3.0 Escrevendo uma migração

Uma vez que você criou uma migração usando um dos geradores, é a hora de trabalhar!

3.1 Criando uma tabela

create_table será um dos métodos mais usados. Tipicamente usada assim

1
2
3
create_table :products do |t|
  t.string :name
end

criará uma tabela products com uma coluna chamada name (e como discutido anteriormente, implicitamente criará uma coluna id).

O objeto “renderizado” (yielded) no bloco permite você criar colunas na tabela. Existe duas formas de se fazer isso. A primeira é algo assim

1
2
3
create_table :products do |t|
  t.column :name, :string, :null => false
end

a segunda forma, que é chamada de migração “sexy”, que elimina redundância dos métodos. Em vez de string, integer, etc os métodos são criados a partir do tipo da coluna, onde os parâmetros subseqüentes são idênticos.

Por padrão create_table criará uma chave primária chamada id. Você pode alterar o nome da chave primária com a opção :primary_key (Não esqueça de atualizar o modelo correspondente) ou se você não precisar de uma chave primária (por exemplo HABTM (has and belongs to many) join table) você pode passar :id => false. Se você precisa passar alguma informação específica, você pode passar um fragmento SQL na opção :options. Por exemplo:

1
2
3
create_table :products, :options => "ENGINE=BLACKHOLE" do |t|
  t.string :name, :null => false
end

Irá anexar ENGINE=BLACKHOLE na sql usada para criar a tabela (Quando se usa MySQL por padrão é usado “ENGINE=InnoDB”).

Os tipos que o Active Record suporta são :primary_key, :string, :text, :integer, :float, :decimal, :datetime, :timestamp, :time, :date, :binary, :boolean.

Eles vão ser mapeados apropriadamente para cada banco de dados, por exemplo com MySQL :string é mapeada para VARCHAR(255). Você pode criar colunas e tipos não suportados pelo Active Record usando uma sintaxe não sexy, por exemplo:

1
2
3
create_table :products do |t|
  t.column :name, 'polygon', :null => false
end

Esta forma, no entanto, dificulta a portabilidade para outros banco de dados.

3.2 Mudando tabelas

O primo mais próximo de create_table é change_table. Usado para alterar tabelas existentes, é similarmente usada como o create_table mas o objeto “rendenrizado” (yielded) para o bloco conhece mais truques. Por exemplo

1
2
3
4
5
6
change_table :products do |t|
  t.remove :description, :name
  t.string :part_number
  t.index :part_number
  t.rename :upccode, :upc_code
end

remove a coluna description e name, adiciona a coluna part_number e adiciona um index nesta mesma coluna. E por ultimo altera o nome da coluna upccode. É o mesmo que fazer

1
2
3
4
5
remove_column :products, :description
remove_column :products, :name
add_column :products, :part_number, :string
add_index :products, :part_number
rename_column :products, :upccode, :upc_code

Você não deve manter repetindo o nome da tabela e de todos os grupos de declarações relatados para modificar uma tabela em particular. Em uma transformação individual os nomes são curtos, por exemplo remove_column torna-se remove e add_index torna-se index.

3.3 Helpers especiais

O Active Record provê alguns atalhos para as funcionalidades mais comuns. Por exemplo, é muito comum adicionar as colunas created_ate updated_at e o método que faz exatamente isso é:

1
2
3
create_table :products do |t|
  t.timestamps
end

Criará uma tabela products com essas duas colunas

1
2
3
change_table :products do |t|
  t.timestamps
end

Adiciona essas duas colunas a uma tabela existente.

Outro helper é chamado de references (Também disponível como belongs_to ). Na sua forma mais simples adiciona alguma habilidade de reutilização.

1
2
3
create_table :products do |t|
  t.references :category
end

então criará a coluna category_id com o tipo apropriado. Note que você deve passar o nome do modelo e não da coluna. O Active Record adicionará o sufixo _id para você. Se você tiver uma associação belongs_to polimórfica então references irá adicionar as colunas referidas

1
2
3
create_table :products do |t|
  t.references :attachment, :polymorphic => { :default => 'Photo' }
end

irá adicionar a coluna attachment_id e a coluna attachment_type com o valor padrão Photo.

Se os helpers fornecidos pelo Active Record não for suficiente, você pode utilizar a função execute para executar SQL arbitrárias.

Para mais detalhes e exemplos de métodos individuais dê uma olhada na documentação da API, em particular a documentação para ActiveRecord::ConnectionAdapters::SchemaStatements (na qual provê os métodos disponíveis nos métodos up e down), ActiveRecord::ConnectionAdapters::TableDefinition (na qual provê os métodos disponíveis para o objeto “rendenrizado” (yielded) por create_table) e o ActiveRecord::ConnectionAdapters::Table (na qual fornece os métodos disponíveis para o objeto “rendenrizado” (yielded) por change_table).

3.4 Escrevendo seu método down

O método down da sua migração deve reverter as transformações concluídas pelo método up. Em outras palavras, o banco de dados deve se manter inalterado se você fizer um up seguido de um down. Por exemplo, se você criar uma tabela no método up você deverá excluí-la no método down. Deve ser inteligente e precisamente inverso ao método up. Por exemplo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class ExampleMigration < ActiveRecord::Migration
  def self.up
    create_table :products do |t|
      t.references :category
    end
    #add a foreign key
    execute "ALTER TABLE products ADD CONSTRAINT fk_products_categories FOREIGN KEY (category_id) REFERENCES categories(id)"
    add_column :users, :home_page_url, :string
    rename_column :users, :email, :email_address
  end

  def self.down
    rename_column :users, :email_address, :email
    remove_column :users, :home_page_url
    execute "ALTER TABLE products DROP FOREIGN KEY fk_products_categories"
    drop_table :products
  end
end

as vezes a sua migração pode fazer algumas coisas irreversíveis, por exemplo quando você destrói alguns dados. Em casos como esse onde você não pode reverter uma migração, você pode lançar IrreversibleMigration para o seu método down. Se alguém tentar reverter a sua migração uma mensagem será mostrada falando que ela não será completa.

E aqui finaliza a segunda parte do artigo.

Até a próxima!

Off-Topic: Eu quero estudar o que eu quero!

| Comments

Estou no ultimo período da faculdade e sinceramente, não aguento mais! Não aguento mais não ter tempo de estudar o que realmente eu quero, para estudar algo que eu vejo que não vai ter utilidade, pelo menos por enquanto.

É realmente muito bom estudar, mas algo que você goste. Eu falo muito para meus amigos que a melhor época do ano é quando estou de férias da faculdade, mas não por que eu fico sem aula, e sim porque eu tenho o tempo que eu quero para estudar o que eu quero!

A educação no Brasil tem um grande problema que é de não escutar realmente quem é o mais importante na história toda, os alunos. Temos uma política de que aluno bom é somente o que passa de ano, é o aluno medíocre, expressão que o Fábio Akita tanto fala, é aquele que esta na média e que não pode se esforçar mais.

É uma política de esmola que acaba no final apenas remediando e não curando tudo que acontece. Agora o emprego é fazer mais filhos para eles irem para escola para poder ganhar mais dinheiro do governo. Podendo pegar esse dinheiro e investir em novas escolas e na melhoria do salário dos professores, fazendo com que pelo menos os filhos dessas pessoas possam ter alguma chance no futuro, e não apenas mais um pegador de esmola do governo.

Eu realmente só precisava desabafar :D Esse não é um post técnico, não é um post Ágil, é apenas um desabafo.

#prontofalei

PHPBurn no GitHub

| Comments

Nós migramos o PHPBurn para o GitHub, então se você tiver vontade de nos ajudar a transformar este ORM faça um fork do projeto e depois nos mande um pull request!

Outra coisa é que quem estiver afim de ganhar uma camiseta, ter um desconto na entrada da PHP Conference 2008 e se juntar a galera da Add4 Comunicação, basta entrar em contato por aqui ou por comercial at add4 ponto com ponto br.

Vamos mudar o mundo, fazer um ORM que consuma menos memória, seja mais rápido, menos burocrático, mais simples e fácil de usar, assim ajudaremos a natureza reduzindo consumo de energia e diminuindo a emissão de CO² :P

PHP Conference 2008, eu vou!

| Comments

Não sei se vocês perceberam, mas coloquei um mini banner do PHP Conference 2008 e sim, eu vou participar, eu e toda a equipe da Add4 Comunicação.

O Klederson Bueno, diretor da Add4 Comunicação, encaminhou uma palestra sobre o PHPBurn e nós vamos apresentá-lo a toda a comunidade, ver as reais necessidades, discutir pontos, enfim, realmente fazer o lançamento.

O PHP Conference vai acontecer de 27 a 29 de Novembro em Osasco. Quem ainda não fez a inscrição, corre lá e faz para assistir nossa palestra :D

E mais sobre o PHPBurn, nós o migramos para o Github, então que tiver interessado em fazer um fork e contribuir, seja bem vindo!

Até a próxima!

Tradução: Rails database Migrations - Parte I

| Comments

Olá, este é o primeiro de quatro partes desse artigo sobre as Migrations do Rails. Antes de se desfrutarem da leitura quero dizer-lhes que se encontrar erros de português ou a tradução com sentido diferente, por favor, comuniquem-me! Avisem-me por email, twitter (caironoleto), ou qualquer mensageiro!! :P

Migrações em Banco de Dados em Rails

Migrações é a forma conveniente de você alterar seu banco de dados de uma maneira organizada e estruturada. Você poderia editar fragmentos de SQL na mão mas você teria a responsabilidade de comunicar aos outros desenvolvedores que eles precisam ir lá e executá-los. Você também necessita acompanhar as mudanças na máquina de produção na próxima vez que você for fazer deploy. O Active Record marca as migrações que já foram executadas e tudo que você precisa fazer é atualizar seu código e rodar rake db:migrate. O Active Record irá trabalhar para que suas migrações sejam executadas.

Migrações é a forma de você descrever essas transformações usando Ruby. A grande coisa disso tudo (como muito das funcionalidades do Active Record) é a independência do banco de dados: você não precisa se preocupar com mais nenhuma sintaxe para CREATE TABLE, ou que você se preocupe sobre variações de SELECT * (você pode abstrair os requisitos específicos de banco de dados SQL). Por exemplo, você poderia usar SQLite 3 no desenvolvimento, mas MySQL em produção.

Você aprenderá tudo sobre migrações incluindo:

  • Os geradores que você pode usar para criá-los
  • Os métodos que o Active Record provê para manipular seu banco de dados
  • As tarefas Rake que você pode manipular
  • Como eles são relativo ao schema.rb

1. Anatomia de uma migração

Antes de eu mergulhar nos detalhes de uma migração, aqui estão alguns exemplos curtos de coisas que você pode fazer:

1
2
3
4
5
6
7
8
9
10
11
12
13
class CreateProducts < ActiveRecord::Migration
  def self.up
    create_table :products do |t|
      t.string :name
      t.text :description
      t.timestamps
    end
  end

  def self.down
    drop_table :products
  end
end

Essa migração adiciona uma tabela chamada products com uma coluna string chamada name e uma coluna text chamada description. Uma chave primária chamada id também será adicionada, no entanto por padrão, não precisamos pedir isso. As colunas timestamps created_at e updated_at que o Active Record preenche automaticamente também são adicionadas. Revertendo essa migração simplesmente remove a tabela.

Migrações não tem limite para alterar o esquema. Você pode usar para corrigir dados errados no banco de dados ou popular novos campos:

1
2
3
4
5
6
7
8
9
10
11
12
class AddReceiveNewsletterToUsers < ActiveRecord::Migration
  def self.up
    change_table :users do |t|
      t.boolean :receive_newsletter, :default => false
    end
    User.update_all ["receive_newsletter = ?", true]
  end

  def self.down
    remove_column :users, :receive_newsletter
  end
end

Esta migração adiciona a coluna receive_newsletter para a tabela users. Nós queremos que o padrão seja falso para novos usuários, mas para os usuários existentes nos consideramos que eles já fizeram a sua opção, então nos usamos o modelo User para setar a bandeira para true para usuários existentes.

1.1 Migrações são classes

A migração é uma subclasse de ActiveRecord::Migration que implementa dois métodos: up (para realizar as transformações exigidas) e down (reverte o que foi feito).

O Active Record prover métodos para executar as tarefas comuns na definição dos dados independente do banco de dados (Você verá mais detalhes mais tarde):

  • create_table
  • change_table
  • drop_table
  • add_column
  • remove_column
  • change_column
  • rename_column
  • add_index
  • remove_index

Se você precisa executar tarefas específicas para seu banco de dados (por exemplo, criar uma chave estrangeira) então a função executepermite executar SQL arbitrarias. As migrações é apenas uma classe regular em Ruby, então você não esta limitado a apenas essas funções. Por exemplo, após adicionar uma coluna, você pode escrever código para setar o valor dessa coluna para dados existentes (se necessário usando seus modelos).

1.2 O que está no nome

Migrações sao armazenadas em arquivos em db/migrate, uma para cada classe de migração. O nome dos arquivos é na forma de YYYYMMDDHHMMSS_create_products.rb, ou seja, uma hora UTC identificando a migração seguida de um sublinhado e seguido do nome da migração. O Nome da classe de migração deve bater com a ultima parte do arquivo. Por exemplo, 20080906120000_create_products.rb deveria definir CreateProducts e 20080906120001_add_details_to_products.rb deveria definer AddDetailsToProducts. Se você acha que necessita mudar o nome do arquivo, então você deve atualizar o nome da classe dentro do arquivo ou então o Rails ira queixar-se que não existe a classe.

Internamente Rails usa apenas o numero da migração (data) para identificá-lo. Antes do Rails 2.1 os números das migrações eram iniciados em 1 e apenas incrementado cada vez que era gerado uma nova migração. Com múltiplos desenvolvedores era mais fácil haver colisões, necessitando você voltar e reordena-los. Você pode reverter para o esquema da velha numeração setando config.active_record.timestamped_migrationspara falseno environment.rb.

A combinação do tempo e o registro que permite executar as migrações foram a forma como o Rails fez para manipular as situações comuns que ocorrem com múltiplos desenvolvedores.

Por exemplo Alice adicionou a migração 20080906120000e 20080906123000e Bob adicionou 20080906124500 e rodou. Alice finaliza suas mudanças e checa nas suas migrações e Bob puxa as mais recentes atualizações. Rails sabe que ele não rodou as duas migrações de Alice assim rake db:migrate irá executá-los (Apesar que a migração do Bob seja executada uma hora mais tarde), e similarmente fazendo regressão da migração não teria executado esses dois métodos.

Claro que isso não substitui a comunicação dentro da equipe, por exemplo, na migração da Alice ela removeu uma tabela que Bob assumiu a existência na sua migração, então claro que um problema irá acontecer.

1.3 Mudando migrações

Ocasionalmente você comete um erro enquanto escrevia a migração. Se você já tiver executado a migração, então você não pode simplesmente editar e executar novamente a migração: Rails acha que a migração já foi executada, então ele não fará nada quando você rodar rake db:migrate. Você deve voltar a migração (por exemplo, com rake db:rollback), editar sua migração e rodar rake db:migratepara a correta versão.

No geral, editar migrações existentes não é uma boa idéia: você criará trabalho extra para você mesmo e para seus parceiros de trabalho e causar um maior problema se a versão da migração for rodada em uma máquina de produção. Em vez disso, você deve escrever uma nova migração para realizar as alterações que você solicita. Editando uma recém migração gerada e que ainda não foi commitada para o controle de versão (ou que geralmente não foi propagada além da sua máquina de desenvolvimento) é relativamente inofensivo. Apenas use com bom senso.

E aqui finaliza a primeira parte deste artigo.

Até a próxima!

Lançado PHPUnit 3.3

| Comments

Olá, na segunda feira (15/09) foi lançado a mais nova versão do PHPUnit 3.3. O Changelog dessa versão trás mais detalhes sobre as nova features.

Até a próxima!