« HE:labs
HE:labs

Controllers mais limpos com facade

Postado por Rafael Fiuza em 06/10/2014

Já teve aquela sensação de que algo é tão comum que todos conhecem mas raramente é aplicado? Então, é sobre um desses casos que irei tratar rapidamente.

Confesso que nunca fui um grande apreciador de usar facade no ruby, principalmente nos controllers. O proprio padrão de linguagem me deixava sempre confuso pela forma livre como é implementada e explicada. Em teoria, um facade é usado para criar uma interface simplificada para algum objeto ou funcionalidade.

Somente quando li sobre as 4 regras basicas da Sandi Metz, mais precisamente a quarta regra, vim a conhecer essa forma de escrever os controllers.

Veja um exemplo (que não deve ser seguido. É um mal exemplo):

 1 class PlayersController < ApplicationController
 2   def show
 3     @player = Player.find_by(params[:id])
 4     @guild_players = @player.guild.players
 5     @player_rank = Rank.for(@player)
 6     @related_players = related_player    
 7   end
 8 
 9   private
10   def related_player
11     return [] unless @player.tags.any?
12     Player.active.with_tag(@player.tags).limit(10)
13   end
14 end

Esse controller expõe 4 variaveis de instância para a view e estamos instanciando 2 models diferentes. Dessa forma, na view, fariamos algo semelhante a:

1 <%= render 'rank', rank: @player_rank %>
2 <%= render 'player' %>
3 <%= render 'guild_players', players: @guild_players %>
4 <%= render 'related_players', players: @related_players %>

Existem varias formas de escrever o controller acima deixando-o simples. Ouso dizer que a mais utilizada é a de extrair para metodos no proprio model. Prefiro o facade quando os metodos são somente usados para representar dados na view, portanto extrair para o model seria desnecessário.

Com facade faríamos uma interface das funcionalidades que queremos representar no controller tornando possível expormos apenas uma variavel para a view e tornando o teste dessas funcionalidades muito mais simples.

 1 class PlayersController < ApplicationController
 2   def show
 3     @profile = ProfileFacade.new(params[:id])
 4   end
 5 end
 6 
 7 class ProfileFacade
 8   def initialize(id)
 9     @player = Player.find(id)
10   end
11 
12   def guild_player
13     player.guild.players
14   end
15 
16   def rank
17     Rank.for(player)
18   end
19 
20   def related_player
21     return [] unless player.tags.any?
22     Player.active.with_tag(player.tags).limit(10)
23   end
24 
25   private
26   attr_reader :player
27 end

E na view

1 <%= render 'rank', rank: @profile.rank %>
2 <%= render 'player' %>
3 <%= render 'guild_players', players: @profile.guild_players %>
4 <%= render 'related_players', players: @profile.related_players %>

Compartilhe

Sabia que nosso blog agora está no Medium? Confira Aqui!