Decorator in Ruby on Rails
Tags: ruby, rails, webdev, design
Published: 2022-01-01 21:12:21

###<center>- English Version -</center>
---

Decorators provide a flexible alternative to subclassing for extending functionality. Simple! :wink:

There are several ways to implement it, but the easiest for me is using [Draper gem](https://rubygems.org/gems/draper).

### 1. Create Rails app
```shell
> rails new decorator-rails
```
   
   
### 2. Install Draper gem
```shell
> bundle add draper
```
Well, from this moment when we create a controller it will automatically create our decorator file in `app/decorator` folder.

### 3. Create user scaffold
```shell
> rails g scaffold User first_name last_name
```
Among other files, the file `app/decorators/user_decorator.rb` has been created automatically.

### 4. Add custom method

```ruby
# app/decorators/user_decorator.rb

class UserDecorator < Draper::Decorator
  delegate_all

  def full_name
    object.first_name + ' ' + object.last_name
  end
end
```
That allows behavior to be added to an individual object without affecting the behavior of other objects from the same class.

### 5. Decorate object in controller
```ruby
# app/controllers/users_controller.rb

def show
  @user = User.find(params[:id]).decorate
end
```

### 6. Show it in View
```erb
# app/views/users/show.html.erb

First name: <%= @user.first_name %>
Last name: <%= @user.last_name %>
Full name: <%= @user.full_name %>
```
And now your view logic has been abstracted and organized to where it should be. This will greatly help you to reduce the code in your view files.

Usually it is used with **Presenters**, but I prefer to do it in another post :wink:

:mag: **Recommended reading**
- [Refactoring GURU](https://refactoring.guru/es/design-patterns/decorator)
- [Wikipedia](https://en.wikipedia.org/wiki/Decorator_pattern)
- [The great code adventure](https://www.thegreatcodeadventure.com/rails-refactoring-part-iii-the-decorator-pattern/)
   
   
Thank you for reading :pray:  
   
:earth_americas: [https://sergioturpin.es](https://sergioturpin.es)
:camera: [Instagram](https://instagram.com/sergioturpin)
:bird: [Twitter](https://twitter.com/sergio_turpin)
:octopus: [GitHub](https://github.com/sturpin)


###<center>- Versión en Español -</center>
---

El patrón **Decorator** nos permite poder encapsular un objeto para que podamos extender su funcionalidad antes de su instanciación, así de simple! :wink:

Existen muchas formas de implementarlo, pero una de las más sencillas es hacerlo con la gema [Draper](https://rubygems.org/gems/draper).

### 1. Creamos la app de Rails
```shell
> rails new decorator-rails
```

### 2. Instalamos la gema Draper
```shell
> bundle add draper
```
Bien, a partir de este momento cuando nosotros creemos un controlador, automáticamente se creará también su decorador en el directorio `app/decorator`.

### 3. Creamos el scaffold de usuario
```shell
> rails g scaffold User first_name last_name
```
Además de otros archivos, el fichero `app/decorators/user_decorator.rb` ha sido creado automáticamente.

### 4. Añadimos un método personalizado

```ruby
# app/decorators/user_decorator.rb

class UserDecorator < Draper::Decorator
  delegate_all

  def full_name
    object.first_name + ' ' + object.last_name
  end
end
```
Esto nos permite agregar comportamiento a un objeto individual sin afectar al comportamiento de otros objetos de la misma clase.

### 5. Decoramos el objeto en el controlador
```ruby
# app/controllers/users_controller.rb

def show
  @user = User.find(params[:id]).decorate
end
```

### 6. Lo mostramos en la Vista
```erb
# app/views/users/show.html.erb

First name: <%= @user.first_name %>
Last name: <%= @user.last_name %>
Full name: <%= @user.full_name %>
```
Y ahora su lógica de vista se ha abstraído y organizado donde debería estar. Esto le ayudará enormemente a reducir el código en sus archivos de vista.

Normalmente es usado conjuntamente con el patrón **Presenters**, pero he preferido hacerlo en otro post :wink:

:mag: **Lecturas recomendadas**
- [Refactoring GURU](https://refactoring.guru/es/design-patterns/decorator)
- [Wikipedia](https://en.wikipedia.org/wiki/Decorator_pattern)
- [The great code adventure](https://www.thegreatcodeadventure.com/rails-refactoring-part-iii-the-decorator-pattern/)
   
   
Gracias por leer :pray:  
   
:earth_americas: [https://sergioturpin.es](https://sergioturpin.es)
:camera: [Instagram](https://instagram.com/sergioturpin)
:bird: [Twitter](https://twitter.com/sergio_turpin)
:octopus: [GitHub](https://github.com/sturpin)