Muito já se falou sobre decorators nos últimos tempos, até mesmo por aqui. Melhorar a legibilidade e remover lógica das views de uma aplicação é um assunto que me interessa já faz algum tempo. Nesse post falarei sobre a alternativa que, no meu ponto de vista, preencheu a lacuna do problema decorators de views no rails .
Há diversas formas de implementar um decorator e já existem inúmeras gems que auxiliam neste trabalho, como o simple_presenter e o draper. O que me incomodava em todas as diversas soluções existentes, é o desenvolvedor ter que passar o objeto ou a coleção de objetos para a classe do decorator para que fosse decorado. Pensando no caso de uma action, ela teria de ser alterada, como pode ser visto no exemplo a seguir:
1 # any controller...
2 def index
3 @users = UserPresenter.map(User.all) # simple presenter
4 @articles = ArticleDecorator.decorate_collection(Article.all) # draper
5 end
Esse tipo de solução sempre me incomodou, e eu mantive minha busca por alguma que funcionasse de forma intrusiva, sem que fosse preciso modificar a chamada na action. E esta solução existe, chama-se active_decorator.
O active_decorator injeta automaticamente o decorator em um model, ou em uma coleção de models ou uma instância do ActiveRecord::Relation a partir de um controller ou renderizando uma view com :collection
ou :object
ou :local
. Sendo assim, não é preciso alterar nenhuma chamada no seu controller.
Vamos ver o exemplo anterior usando o active decorator.
1 # any controller...
2 def index
3 @users = User.all
4 @articles = Article.all
5 end
Existindo um UserDecorator
e um ArticleDecorator
, os objetos das coleções serão automaticamente decorados quando forem ser usados nas views.
Veja um exemplo mais completo:
1 # any controller...
2 def index
3 @user = current_user
4 @articles = current_user.articles
5 end
6
7 # user decorator
8 module UserDecorator
9
10 def full_name
11 "#{first_name}-#{last_name}"
12 end
13
14 end
15
16 # article decorator
17 module ArticleDecorator
18
19 def link_to_publish
20 if published?
21 "On air!"
22 else
23 link_to "Publish", publish_article_path(self)
24 end
25 end
26 end
1 # app/views/articles/index.erb
2
3 Olá <%= @user.full_name %>
4
5 <ul>
6 <% @articles.each do |article| %>
7 <li>
8 <%= article.title %>
9 <%= article.link_to_publish %>
10 </li>
11 <% end %>
12 </ul>
O active decorator é totalmente "plugável" a uma aplicação existente o que reduz bastante o esforço de implementação de decorators, facilitando a implementação gradual.
Abraços, Rodrigo Pinto.
Comentários
Included file post/disqus_thread.html not found in _includes directory