mergulhao.info
Por Sylvestre Mergulhão
Sylvestre Mergulhão é programador web e fundador da HE:labs.
Veja também minhas palestras no Speaker Deck e me acompanhe no twitter @smergulhao.
acts_as_taggable_on_steroids e will_paginate
Postado em 21/01/2009
Num dos projetos que trabalho utilizo o plugin acts_as_taggable_on_steroids. Pela primeira vez fui fazer paginação de elementos com tags utilizando o will_paginate. O acts_as_taggable_on_steroids fornece o método de classe find_tagged_with que serve para buscar por items com uma determinada tag:
Post.find\_tagged\_with('rails')
E é possível fazer paginação utilizando o método paginate_tagged_with, mas o problema é que ele não funciona como deveria. Apesar de fazer a paginação funcionar corretamente, a sql que ele gera para fazer o count dos elementos não é correta. Se usado sem conditions, ele gera o número de páginas considerando todos os elementos da base. Eu escrevi o seguinte monkey patch, que coloquei no /lib do projeto:
module ActiveRecord
module Acts
module Taggable
module SingletonMethods
def paginate_tagged_with(tags, args = {})
options = find_options_for_find_tagged_with(tags, :match_all => true)
options.merge!(args)
paginate(options.merge(:count => { :select => options[:select].gsub("#{table_name}.*", "#{table_name}.id") }))
end
end
end
end
end
Para usar basta colocar no seu controller algo como:
@posts = Post.paginate_tagged_with(params[:tag_id], :page => params[:page] || 1)
Também escrevi uma spec para testar o funcionamento. Ela só faz sentido dentro do contexto do meu projeto, mas basta você modificar as fixtures, os modelos, etc, de acordo com seu projeto.
describe Post do
it "should return the correct total_pages to will_paginate" do
post = posts(:blog_post)
5.times do
new_post = BlogPost.new(post.attributes)
new_post.tag_list = 'global'
new_post.save
end
paginator = BlogPost.paginate_tagged_with('global', :page => 1, :per_page => 2)
paginator.total_entries.should == 6
paginator.total_pages.should == 3
end
end