[Tiago Motta] Cuidado ao cachear named_scope no Rails

Deve-se tomar cuidado ao cachear o acesso a um named_scope pois ele tem um carregamento de forma preguiçosa, o famoso lazy load. Assim, o código abaixo gravaria no cache não os atores femininos, mas sim todos os atores.

class Filme    #...  def atores_femininos_cacheado    Rails.cache.fetch("#{self.id}:atores-principais") { self.atores.femininos }  end

class Ator  #...  named_scope :femininos, :conditions => { :sexo => 'F' }

Se você observar o log, verá que o rails executará a query sem as condições definidas na classe Ator para o named_scope :femininos. E que após ser cacheado, será essa a query que deixará de ser executada.

A query para buscar atores femininos do named_scope só será realmente executada quando algum método do objeto retornado pelo método .atores.femininos for chamado. Veja no exemplo abaixo:

@filme = Filme.find_by_id 10filme.atores_femininos_cacheado.last

Ou seja, o cacheamento não está servindo ao propósito definido. Uma solução para isso é cachear diretamente o resultado de um find, como pode ser visto abaixo:

class Filme    #...  def atores_femininos_cacheado    Rails.cache.fetch("#{self.id}:atores-principais") do      Ator.find_all_by_filme_id self, :conditions => { :sexo => 'F' }    end  end