Rinaldi Fonseca

Rails Metal e Devise

13 de maio de 2011

O Rails Metal está disponível desde a versão 2.3, mas com a nova arquitetura do Action Controller no Rails 3, ficou muito mais fácil adicionar funcionalidades e recursos.

A principal vantagem da utilização do Rails Metal torna-se evidente quando não necessitamos carregar toda a stack do Rails para realizar determinada atividade.

Um exemplo prático é a criação de APIs. Podemos por exemplo, ter uma determinada action em nossa aplicação, que é responsável por apenas devolver um JSON. Neste caso o uso do Rails Metal é extremamente indicado, pois evitamos carregar funcionalidades nas quais não precisaremos..

De forma resumida, o Rails Metal praticamente provê um código suficiente para uma aplicação Rack.

No Rails 3 temos o ActionController::Base que herda de ActionController::Metal, que por sua vez herda de AbstractController::Base.

Esta nova arquitetura nos dá muita flexibilidade para utilizar somente o que necessitamos.
Veja um exemplo prático abaixo:

Download de arquivos

Vamos imaginar que nossa aplicação possui uma funcionalidade de upload de arquivos, e que posteriormente desejamos disponibilizá-los para download. Porém existe uma restrição: Apenas usuários autenticados poderão fazer o download dos arquivos.

Neste caso, não podemos simplesmente fazer o upload dos arquivos dentro do diretório public. Caso contrário os arquivos estariam disponíveis sem autenticação.

Uma possível solução seria realizar o upload em um diretório fora de public, e em seguida criar um controller que direciona o usuário para o download do arquivo em questão.
Esta é uma situação ideal para usar o Rails Metal, afinal precisamos apenas verificar a autenticação do usuário e em seguida enviar o arquivo.

Abaixo uma possível implementação de exemplo:

Em nosso arquivo routes.rb teríamos algo do tipo:

 match '/download/:file' => DownloadController.action(:file)

E nosso controller seria:

class DownloadController < ActionController::Metal
 
  before_filter :authenticate_user!
 
  def file
    #implementação da lógica para recuperar qual arquivo o usuário deseja
    send_file("/path/to/your/file.csv")
  end
 
end

Simples e prático! Porém esta implementação não irá funcionar, pois precisamos incluir alguns módulos em nosso controller.

  • Para utilizarmos o send_file precisamos incluir o módulo ActionController::Streaming
  • Para utilizar o before_filter precisamos incluir o módulo AbstractController::Callbacks
  • Para verificarmos a autenticação do usuário com o Devise precisamos incluir o módulo Devise::Controllers::Helpers
  • E para finalizar precisaremos também do módulo ActionController::Helpers pois o Devise utiliza o método helper_method para criação dinâmica do método :authenticate_user!

Agora nossa implementação seria:

class DownloadController < ActionController::Metal
 
 include ActionController::Streaming
 include AbstractController::Callbacks
 include ActionController::Helpers
 include Devise::Controllers::Helpers
 
 before_filter :authenticate_user!
 
  def file
    #implementação da lógica para recuperar qual arquivo o usuário deseja
    send_file("/path/to/your/file.csv")
  end
 
end

Com isso temos um controller mais leve e ainda podemos utilizar diversas funcionalidades que as demais gems, módulos etc nos fornecem.

Nenhum Comentário »

Nenhum comentário ainda.

Feed RSS dos comentários deste post URL de TrackBack

Deixe um comentário

Spam protection by WP Captcha-Free