O Carlos Brando vem fazendo um excelente trabalho em trazer para nós as novidades do Rails Edge (no caso, o 2.2). Mas ao me deparar com esta atualização não pude me conter em blogar sobre. Na verdade, apenas traduzir o artigo do Ryan.
———–
Conditional-gets são uma facilidade da especificação do HTTP que fornece um método de os servidores we comunicarem aos brosers que a resposta para a requisição GET não mudou desde a última requisição e que o cache do browser pode ser usado com segurança.
Eles funcionam usando os cabeçalhos HTTP_IF_NONE_MATCH e HTTP_IF_MODIFIED_SINCE para passar para frente e para trás um identificador único do conteúdo e o timestamp de quando o conteúdo foi modificado pela última vez. Se o browser fizer a requisição onde o identificador do conteúdo (etag) ou a data da última modificação bater com a versão do servidor então o servidor precisa apenas enviar de volta uma resposta vazia com um status de “não modificado” (304).
É do servidor (nós) a responsabilidade de olhar a data da última modificação e o cabeçalho if-none-match e determinar quando ou não enviar a resposta completa (com a renderização da página, por exemplo). Com este novo suporte a conditional-get no rails, isto se torna uma tarefa muito fácil:
class ArticlesController < ApplicationController def show @article = Article.find(params[:id]) # Define o cabeçalho da resposta para refletir exatamente # o estado do objeto requisitado response.last_modified = @article.published_at.utc response.etag = @article # Se o estado da requisição é o mesmo do estado no servidor # então sabemos que não precisamos enviar todo o resultado if request.fresh?(response) head :not_modified else respond_to do |wants| # normal response processing end end end end
O valor do etag é calculado para você com o metodo setter etag=. Tudo que você tem que fazer é prover um único objeto ou array de objetos que definem de forma única a identificação desta requisição. Neste exemplo o artigo por si mesmo contém toda a informação que identifica o estado desta requisição. De qualquer forma, você pode precisar de usar mais de uma chave em seu aplicativo. Como para uma requisição específica para cada usuário:
response.etag = [@article, current_user]
O método request.fresh?(response) é quem dirá a você se a requisição casa com o valor de last-modified-since ou if-none-match da resposta que está sendo enviada. Se sim, você pode evitar de responder todo o conteúdo e economizar alguma (ou muita!) banda.
Também é possível você evitar de acessar o banco de dados se seu aplicativo trata com páginas completamente estáticas armazenadas no banco de dados (isso é raro):
class ArticlesController < ApplicationController def show # Se o artigo não muda, o etag pode se basear apenas em # ítems que temos na requisição response.etag = [:article, params[:id]] # Se o estado da requisição é o mesmo do servidor # podemos evitar também de acessar o banco de dados if request.fresh?(response) head :not_modified else @article = Article.find(params[:id]) respond_to do |wants| ... end end end end
Então, seja um bom cidadão e faça suas requisições compatíveis com conditional-get. Isto é a coisa certa a ser feita – e melhoram também a performance de seus programas.
—-
Vale notar, que você pode também usar estes cabeçalhos para acessar webservices (principalmente os feitos em Rails agora
) fazendo requisição de XML, se você, por exemplo, estiver guardando os dados que você acessou e guardar a data em que isto foi feito, assim você economisa ainda mais banda!







[...] Carlos J?nior j? escreveu sobre isto no blog da milk-it. Provavelmente teremos suporte a ETags no Rails 2.2. Eu disse provavelmente porque isto ainda n?o [...]