Edge Rails: Melhorando a performance usando ETags - Nome do Jogo
Edge Rails: Melhorando a performance usando ETags
O 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 foi incluído no branch oficial do Rails, mas como é algo importante e está sendo feito pelo core team, é quase certo de que será.
Antes de começar a falar sobre isto, deixa eu tentar explicar o que são ETags (Entity Tags). Etags seriam de uma forma grosseira identificadores associados a cada recurso para determinar se o arquivo que está no servidor é o mesmo que está no cache do browser. No caso, o recurso seria uma página em HTML, mas também poderia ser um XML ou JSON.
Cabe ao servidor a responsabilidade de verificar se o recurso solicitado é igual dos dois lados. Caso o servidor confirme que o recurso armazenado no cache do browser do usuário é exatamente o mesmo que seria enviado de volta para ele, ao invés de devolver todo o conteúdo do recurso novamente ele apenas retorna um status 304 (Not Modified) e o browser usará o que está em seu cache.
Servidores Web como o Apache e o IIS já sabem fazer isto para página estáticas. Mas quando o conteúdo é dinâmico, como na maioria das páginas de um projeto Ruby on Rails, a responsabilidade é todo nossa.
O objeto response ganhou dois novos métodos, o last_modified= e o etag= (note o sinal de igualdade "="). Quando você atribuir valores a estes métodos eles serão repassados aos cabeçalhos HTTP_IF_MODIFIED_SINCE e HTTP_IF_NONE_MATCH respectivamente. Quando uma nova requisição (request) deste recurso for feita ela retornará com estes cabeçalhos permitindo que você possa comparar com o novo valor informado no response e decidir se quer enviar todo o conteúdo do recurso novamente ou apenas um status 304.
Vamos ao código (roubando o exemplo dado por Ryan Daigle no seu blog):
# informado o identificador
response.last_modified = @article.published_at.utc
response.etag = @article
# verificando se houve mudanças
# retornando conteúdo normalmente
Note que estou atribuindo valores para response.last_modified e response.etag, e logo em seguinda usando o método request.fresh?(response) para determinar se houve alguma mudança ou não. Caso os dois cabeçalhos continuem iguais eu apenas retorno um status 304 e o browser do usuário usará o conteúdo que está armazenado no seu cache.
Quanto ao método etag, também podemos passar um array se for o caso:
response.etag = [@article, current_user]
A forma como foi implementado isto no Rails está causando um certo desconforto em muita gente e várias outras formas foram sugeridas pela comunidade, então possivelmente isto pode mudar antes do lançamento da versão 2.2.