Views Orientadas a Objeto com Decorators
Você já se pegou criando muitos helpers em aplicações Rails?
Os helpers nos ajudam oferecendo um recurso extra para trabalharmos a lógica da apresentação de dados. Porém, eles não são orientados a objeto, isso significa que podemos estar escrevendo código desnecessariamente e de maneira não elegante neles.
Case
Hoje estava trabalhando num projeto e me deparei com o seguinte cenário: eventos podem ter um preço mínimo e um preço máximo, ou apenas um dos dois. Como lidar com essa lógica na apresentação de dados?
Utilizar Helpers (wrong way)
A primeira (e talvez) mais comum solução seja criar uma função em um helper para cuidar disso:
Aqui, recebemos a instância do evento como parâmetro e retornamos uma string com os preços presentes formatados e separados por -
.
Mas, se essa lógica de apresentação faz parte de todos eventos, porque devo ficar passando toda hora o evento que desejo como parâmetro? Isso cheira mal.
Utilizar Decorators
Em programação orientada a objetos, existe um design pattern chamado decorator, ele serve para adicionar responsabilidades há um objeto, extendendo assim suas capacidades.
Existe uma outra nomenclatura também, chamada presenter, ela nada mais é do que um decorator, só que unicamente responsável por extender funcionalidades de lógica de apresentação.
Mas independente do nome que você chamar, já sabemos a sua função e daqui pra frente irei chamar de decorators.
Por padrão, o Rails não vem com nada pronto para trabalhar com esse design, mas existem várias gemas criadas pela comunidade que dão conta do recado.
Segundo o site "The Ruby Toolbox", a gema Draper é a mais utilizada para isso (inclusive o episódio #286 do Railscasts é sobre ela), porém, eu não gostei de ter que chamar o método decorate
toda vez que estiver instanciando o objeto no controller.
Preferi a ActiveDecorator, que foi criada pelo Akira Matsuda (mesmo criador do Kaminari) e irei mostrar agora como utilizar:
Veja a diferença! Não precisamos passar nenhum parâmetro para o método price
, apenas chamamos os atributos min_price
e max_price
e o decorator já sabe que se trata de atributos do model Event.
Use o comando rails g decorator model
(substituindo "model" pelo nome de seu modelo) para criar o decorator dentro da pasta app/decorators
.
Conclusão
- Use decorator quando helpers ou métodos do model dizerem respeito há um comportamento de apresentação de dados (criar tags HTML, utilizar helpers do Rails..) relacionados há um ou mais objetos.
- Mantenha a lógica de apresentação em um único lugar
- Utilize helpers apenas para lógicas que não dizem respeito há um objeto
- Siga o SRP (Single Responsible Principle), cada um faz seu papel
Essa foi dica de hoje, deixe sua opinião nos comentários.
Abraços.