Quando comecei a escrever código em Rails, algumas coisas ainda não estavam tão claras na minha cabeça, principalmente como o RESTful funciona. Este artigo irá mostrar como unificar 2 metodos do meu controller que fazem a mesma coisa, para responder de maneiras diferentes. Este código está na minha aplicação de podcasts. Lembre-se de ter testes no seu código, vou suprimi-los aqui, sem eles sua refatoração é duvidosa.
1) Qual é a idéia?
Eu precisava hospedar meus arquivos mp3 em outro servidor, pois tenho pouco espaço para isso. Mas e se eu trocasse de lugar os arquivos? Eu teria sempre que quebrar os links de mp3 do meu sistema. Então eu guardo no banco o link onde está o meu podcast(o ouvinte não precisa saber disso rs).
As duas actions a seguir refletem o seguinte comportamento:
Quando o usuário entra em http://podcasts.tudoquequerosaber.com/podcast/Pod7-IvanSanchez ele é enviado para a action show, que irá mostrar os comentários do Podcast.
E para fazer o download ou escutar o podcast é so adicionar .mp3 ao final do link http://podcasts.tudoquequerosaber.com/podcast/Pod7-IvanSanchez.mp3, não importa onde está o arquivo, o sistema tem que mandar o mp3. Esta requisição envia o params[:page_name] = Pod7-IvanSanchez para a action download pedindo uma requisição “audio/mpeg”. Você pode usar essa URL no seu player de mp3.
Esta é a implementação inicial, bem feia por sinal:
def download
@podcast = Podcast.find_by_urlname(params[:page_name])
unless @podcast.nil?
respond_to do |format|
format.mp3 do
Counter.create(:podcast_id => @podcast.id)
redirect_to @podcast.link
end
end
else
redirect_to :action => 'index'
end
end
def show
@podcast = Podcast.find_by_urlname(params[:page_name])
if @podcast.nil?
redirect_to :action => "index"
end
end
Isto nao está nada bom, e as coisas não podem ficar feias assim com Ruby/Rails. Vamos uni-las na action show, fazendo que action possa responder como mp3 e html.
def show
@podcast = Podcast.find_by_urlname(params[:page_name])
unless @podcast.nil?
respond_to do |format|
format.html #<<<<<<<<<<<<<<<<<<<<
format.mp3 do
Counter.create(:podcast_id => @podcast.id)
redirect_to @podcast.link
end
end
else
redirect_to :action => 'index'
end
end
2) O que faz o método find_by_
Acho que todos já sabem que o find_by_nome_do_campo_da_tabela, utiliza o method missing do ruby, mas ele tem um comportamento bem mais funcional.
Fazer um:
Podcast.find_by_urlname(params[:page_name])
é a mesma coisa que utilizar:
Podcast.find(:first, :conditions => ["urlname = ?", params[:page_name])
caso esta pesquisa não retorne nada, ganhamos um nil de presente. Posso deixar meu codigo mais legível:
def show
@podcast = Podcast.find_by_urlname(params[:page_name])
if @podcast #<<<<<<<<<<<<<<<<<<<<
respond_to do |format|
format.html
format.mp3 do
Counter.create(:podcast_id => @podcast.id)
redirect_to @podcast.link
end
end
else
redirect_to :action => 'index'
end
end
3) Refactoring Extrair método
Posso deixar meu método show ainda mais legível, vamos extrair todo comportamento do format.mp3 dentro do respond_to, é uma das refatorações mais utilizadas do livro de Martin Fowler Refactoring: Improving the Design of Existing Code. Vamos lá novamente:
def show
@podcast = Podcast.find_by_urlname(params[:page_name])
if @podcast
respond_to do |format|
format.html
format.mp3 {add_counter_and_redirect_to_mp3(@podcast)}
end
else
redirect_to :action => "index"
end
end
private
def add_counter_and_redirect_to_mp3(podcast)
Counter.create(:podcast_id => podcast.id)
redirect_to podcast.link
end
A action show é uma das 7 que o restful do Rails nos entrega. Agora posso partir para este novo passo. Mas fica para a próxima. Todos esses passos foram garantidos pelos testes funcionais. Não esqueçam deles. ;)
Deixe seu comentário.