Conhecendo as opções de cache do Rails 2.1
14/07/08
O Ruby on Rails 2.1, dentre outras novidades, trouxe suporte nativo a cache, com diversas opções de armazenamento.
O destaque vai para o suporte ao Memcache, de longe uma das opções mais utilizadas.
Todas essas novidades foram adicionadas ao módulo
ActiveSupport::Cache, que você confere neste artigo.
Configurando as opções de cache
Para definir qual o tipo de cache que você quer utilizar, altere a nova configuração cache_store, adicionada aos arquivos de ambiente de sua aplicação no diretório config/environments/*.rb. Você pode escolher entre :memory_store, :file_store, :mem_cache_store e drb.
config.cache_store = :memory_store
config.cache_store = :file_store, '/path/to/cache'
config.cache_store = :mem_cache_store
config.cache_store = :drb_store, "druby://localhost:2250"
config.cache_store = :mem_cache_store, '127.0.0.1:11211', '127.0.0.1:11212', {:namespace => 'myapp'}
A opção padrão de cache é :memory_store, a menos que o diretório tmp/cache exista; neste caso, a opção utilizada será :file_store.
Vale lembrar que se você utilizar uma opção cujo ambiente não está funcionando corretamente, sua aplicação não deixará de funcionar. Este comportamento é perfeito para trabalho em equipe, onde um desenvolvedor pode configurar seu ambiente para utilizar o Memcache enquanto os outros não precisam se importar com isso naquele momento.
Como funciona
Todas as funções de cache estão disponíveis no objeto Rails.cache.
Para gravar qualquer coisa no cache você deve utilizar o método write.
Rails.cache.write('some_identifier', 'some_value')
Você pode passar qualquer valor para ser gravado no cache, incluindo objetos de ActiveRecord.
@user = User.first
Rails.cache.write(@user.cache_key, @user)
O ActiveRecord adiciona um método que gera uma chave única para cada objeto, chamado cache_key.
Este método gera uma chave como "users/1-20080713185825", que você possa acessar e expirar o objeto sempre que precisar.
Por padrão, a chave gerada irá utilizar o nome do modelo, o id do objeto e a data de atualização, disponível através do atributo
updated_at.
Para ler um objeto do cache, você pode utilizar o método read.
Ele recebe um único argumento que identifica o objeto. Caso o objeto não seja encontrado, o valor nil
será retornado.
Rails.cache.read('some_identifier')
Você pode verificar se um item existe no cache com o método exist?.
Rails.cache.exist?('some_identifier')
Você pode estar se perguntando se você precisa utiliza o método exist? juntamente com read e write para acessar um objeto caso ele exista e gravar um novo item caso ele não seja encontrado. Na verdade, você pode utilizar o método fetch que tenta acessar um item no cache e, caso ele não exista, executa o bloco que é passado e faz a gravação em cache automaticamente.
@users = Rails.cache.fetch('users/all') { User.all }
O método fetch pode receber um hash de opções. No momento, a única opção disponível é :expires_in, que permite alterar o tempo de expiração do cache somente para aquele objeto.
@users = Rails.cache.fetch('users/all', :expires_in => 30.minutes) { User.all }
Para o caso de você estar acessando um único objeto, você pode sobrescrever o método cache_key de modo que ele não gere a chave com o a data de atualização.
class User < ActiveRecord::Base
def cache_key
"users/#{id}"
end
end
Assim, você pode acessar os objetos de maneira mais simples. Veja um exemplo de como isso funcionaria em uma action do controller users.
class UsersControllers < ApplicationController
def show
@user = Rails.cache.fetch("users/#{params[:id]}") { User.find(params[:id]) }
end
end
E se você segue a idéia de encapsular toda a lógica nos modelos, existe sempre a opção de cuidar do cache desta maneira.
class User < ActiveRecord::Base
def self.find_recent_users
Rails.cache.fetch('users/recent') { all :order => 'created_at desc', :limit => 10 }
end
end
Você também pode remover qualquer item do cache com o método delete, que retorna true or false.
Rails.cache.delete('users/1')
Finalizando
É isso! Acredito que este artigo cubra as principais funcionalidades de cache que foram adicionadas à versão 2.1. Dúvidas, sugestões ou correções, envie um comentário!
- Permalink
- Trackback
- Comentários (4)
- Ao som de: Kay Hanley – Mean Streak
Mudança no RSpec 1.1.4 remove inclusão automática de módulos
25/06/08
No RSpec 1.1.4, a inclusão de módulos deixou de ser automática. Você só irá perceber esta mudança se está testando algum módulo, como é o caso dos helpers.
Antes, você só precisava fazer algo como isto:
describe ApplicationHelper do
it "should render flash[:notice]" do
flash[:notice] = "Some notice"
flash_messages.should have_tag('p.notice', 'Some notice')
end
end
Nesta nova versão, se você tentar testar o método flash_messages, irá receber uma mensagem de aviso:
Modules will no longer be automatically included in RSpec version 1.1.4. Called from ./spec/helpers/application_helper_spec.rb:6
A solução é fazer a inclusão manual dos módulos, como este exemplo
describe ApplicationHelper do
include ApplicationHelper
it "should render flash[:notice]" do
flash[:notice] = "Some notice"
flash_messages.should have_tag('p.notice', 'Some notice')
end
end
ou utilizar o objeto helper, que possui todos os métodos do módulo especificado em describe
describe ApplicationHelper do
it "should render flash[:notice]" do
flash[:notice] = "Some notice"
helper.flash_messages.should have_tag('p.notice', 'Some notice')
end
end
Em um primeiro momento, eu não tinha gostado nem um pouco desta alteração, mas depois de
ler os motivos, acho que ficou muito melhor. Você teria dúvidas de que está testando um helper se utilizar helper.flash_messages? E se você tivesse um módulo com um método describe?
As respostas já justificam a alteração por si sós.
- Permalink
- Trackback
- Comentários (0)
- Ao som de: Propagandhi – A Public Dis-service Announcement From Shell
Otimizando o Autotest
20/06/08
Toda vez que executo o Autotest,
não demora muito para o cooler do meu Macbook
ligar e parecer que vai decolar!
O problema é que o Autotest busca alterações nos arquivos a cada segundo, o que ocasiona um uso muito intenso da CPU.
Para resolver este problema, basta você aumentar este tempo de verificação que, no exemplo abaixo, foi definido como 5 segundos. Além disso, podemos ignorar alguns diretórios, diminuindo os arquivos que precisam ser verificados. Abra seu arquivo "~/.autotest" e adicione o código abaixo.
Autotest.add_hook :initialize do |at|
at.sleep = 5
%w{.svn .git public vendor}.each { |exception| at.add_exception(exception) }
end
Simples, rápido e, o melhor de tudo, silencioso!
- Permalink
- Trackback
- Comentários (0)
- Ao som de: Propagandhi – A Public Dis-service Announcement From Shell
