sábado, 21 de fevereiro de 2009

Upload de imagens no Rails com Paperclip

Hoje vou escrever um tutorial sobre como fazer upload e redimensionamento de imagens no Ruby on Rails (RoR) utilizando o plug-in Paperclip.

O Paperclip é um plug-in muito simples de usar, estou utilizando ele em um projeto pessoal e é meu favorito para esse tipo de tarefa.

Vou ensinar como usá-lo dando um exemplo prático. Vamos criar um projeto que tem uma classe user (usuário) com os campos name (nome) e picture (fotografia).

Vamos criar uma tela de cadastro de usuários e uma tela que liste os usuários cadastrados, para podermos ver o Paperclip em ação.

Criando o projeto.

Para começar vamos criar nosso projeto, para isso vá para o seu diretório de projetos e digite o comando:

$ rails example --database=mysql

O nome do meu projeto é example e estou utilizando banco de dados mysql. Se você quiser utilizar outro nome ou banco de dados fique à vontade.

Estou utilizando nome de variáveis em inglês pois recentemente comecei a seguir a recomendação que o Carlos Brando fez no post Rails Way #3: Nomes de métodos e variáveis devem ser óbvios, recomendo a leitura.

Configurando o banco de dados.

Agora que o nosso projeto está criado vamos configurar o banco de dados, para isso abra o arquivo que está em config/database.yml com seu editor de textos.

Escreva a senha de seu banco de dados nos respectivos lugares para os bancos development, test e production.

Ficará similar à figura abaixo (a senha do meu banco de dados é root):



Instalando o plug-in Paperclip.

Agora vamos instalar o plugin do Paperclip em nosso projeto. Digite, no diretório do projeto, o comando:

$ script/plugin install git://github.com/thoughtbot/paperclip.git

Ps. Você precisará ter o git instalado para executar esse comando, se você ainda não tem confira o post Instalar GIT no Ubuntu.

Criando o model user.

Agora vamos criar a classe user.

Como dito anterirmente, nossa classe terá os campos name e picture, que será o campo que amazenará a fotografia do usuário.

Para que o paperclip funcione, ao invéz de criar os campo picture no model, criaremos os seguintes campos:
  • picture_file_name (string)
  • picture_content_type (string)
  • picture_file_size (integer)
  • picture_updated_at (datetime)
Onde picture é o nome que usaremos para se referir a imagem. Portanto se o nome que você escolheu fosse image, por exemplo, os nomes dos campos seriam image_updated_at, image_file_name e por aí vai.

Digite o seguinte comando para criar o model user:

$ script/generate model user name:string picture_file_name:string picture_content_type:string picture_file_size:integer picture_updated_at:datetime

Configurando o campo picture na classe user.

Agora vamos dizer para a classe user que ela tem uma imagem que responde pelo nome de picture.

Para isso abra o arquivo que está em app/model/user.rb e adicione dentro da classe a linha:

has_attached_file :picture, :styles => {:small => "150x150", :large => "550x550"}

Onde small e large são tamanhos que eu defini para que minha imagem tenha. Então quando eu fizer o upload de uma imagem o paperclip salvará, também, uma cópia dela nos tamanhos que eu especifiquei.

Você pode definir mais tamanhos se quiser (ou menos) e os nomes ficam a seu critério.

O arquivo ficará assim (clique na imagem para ampliar):



Criando o banco de dados.

Agora para criar os bancos de dados e a tabela users vamos utilizar o rake.
Digite os comandos:

$ rake db:create:all
$ rake db:migrate


Criando o controller para user.

Agora vamos criar um controller para manipular o model user. Digite o comando:

script/generate controller users

Abra o arquivo gerado (app/controllers/users_controller.rb) e vamos criar as actions index, new e create. Por enquanto vamos deixá-las em branco, ficará assim:



A action index listará os usuários cadastrados, a action new carregará o formulário de cadastro e a create criará o usuário digitado no formulário.

Criando o formulário de cadastro.

Vamos criar a view para o formulário de cadastro, crie o arquivo app/views/new.html.erb

Dentro dele crie o formulário de cadastro, veja o meu de exemplo (clique: na imagem para ampliá-la):



Lembrando que todo formulário que possui um campo file_field precisa ter o parâmetro :html => { :multipart => true } para funcionar. Senão o navegador não irá transferir o arquivo.

Criando a action create.

Agora vamos criar a action que cadastrará os dados do formulário, a action create.

Ela ficará assim (app/controllers/users_controller.rb):



Essa action recebe os dados do formulário, cria um objeto do tipo user com esses dados e o salva no banco de dados. Se o procedimento deu certo ela vai para o index, que listará os usuários cadastrados, senão ela retorna para a página de cadastro.

Criando a view para o index.

Agora que nosso projeto já cadastra usuários, vamos criar a view index para listá-los.

Primeiramente faça com que a action index do controller users carregue uma variável com os usuários cadastrados, para isso (app/controllers/users_controller.rb):



Agora, para criar a view, crie o arquivo app/view/users/index.html.erb

Veja o meu de exemplo (clique na imagem para ampliá-la):



Para exibir a imagem eu usei:

<%= image_tag u.picture.url(:small) %>

Onde u é o nome do objeto, picture é nosso campo de imagem, url retorna o endereço da imagem e :small é o tramanho que eu defini anteriormente.

Para esse exemplo os seguintes códigos também funcionariam:

<%= image_tag u.picture.url() %>
<%= image_tag u.picture.url(:small) %>
<%= image_tag u.picture.url(:large) %>


Concluindo.

Agora já temos nosso sistema funcionando com upload e redimensionamento de imagens atravéz do plugin Paperclip.

Digite:

$ script/server

para iniciar o servidor e acesse: http://localhost:3000/users

Resumindo.

Vou resumir o que se deve fazer para trabalhar com Paperclip:
  • Instalar o plug-in em seu projeto.
  • Criar os campos em sua model / tabela: sua_imagem_file_name (string), sua_imagem_content_type (string), sua_imagem_file_size (integer), sua_imagem_updated_at (datetime).
  • Definir, em seu model a propriedade has_attached_file com o nome do seu campo e estilos, se necessário.
  • Utilizar um formulário de cadastro com parâmetro multipart=>true e o campo tipo file_field.
  • Para exibir, utilizar o método url do campo de imagem passando por parâmetro o tamanho da imagem que foi previamente definido.
Bom pessoal espero que tenham gostado do post, qualquer dúvida postem um comentário ou me mandem um e-mail (está escrito no meu perfil do blog).

Abraços e até o próximo post!

5 comentários:

ThalesHerbert disse...

o upload funciona perfeitamente... mas estou com um problema: criei uma action editar que utiliza a mesma view de cadastrar. quando a view é renderizada, o campo file_field não é preenchido...

Bruno Grasselli disse...

Olá ThalesHerbert,

Faz o seguinte, se você ainda estiver com esse problema me passa seu código no e-mail (ou github) e eu dou uma analisada para você.

Abraços.

Renato Ramiro disse...

O upload nao está funcionando. Aparece dois erros:
* Picture /tmp/stream20091021-6442-1btwgro-0 is not recognized by the 'identify' command.
* Picture /tmp/stream20091021-6442-1btwgro-0 is not recognized by the 'identify' command.

Pode me ajudar??

danilolau disse...

Eu tive o mesmo problema Renato,
eu resolvi assim:

sudo apt-get remove --purge librmagick-ruby-doc librmagick-ruby1.8

sudo apt-get install imagemagick libmagick9-dev ruby1.8-dev

sudo gem install rmagick
e funcionou, espero que de certo pra vc tb...

Ah, e na minha classe model eu adicionou require 'paperclip', eu nao sei se faz diferença, mas por via das dúvidas neh...

flw

Marco Antonio disse...

parece que o endereco para istalacao do paperclip nao esta funcionando:
script/plugin install git://github.com/thoughtbot/paperclip.git