Rails design pattern
Tags: rails, ruby, programming
Published: 2021-11-18 10:13:40

If you are a Rails-developer you know at least MVC pattern. Most of us know of course that it has some limitations in terms of structuring your code (fat controllers/models) and in some point of your developer's path you start thinking about code quality and here I mean not code style and other minor things but more general - single responsibility principal (SRP) and how we can organize code in order to make it real, Liskov’s Substitution Principle etc.

Ok, we have spotted a problem and what can we do with it?
As you can have noticed - SOLID principles and general OO design are our tools. But they are too general. Are there something more specific? Googling will provide you at least next possible patterns: 
* Builder
* Decorator
* Form
* Interactor
* Observer
* Policy
* Presenter
* Query
* Service
* Value

I am not going to retell them, you can easily find definitions. But I want to light on next moment: how many from them you are using in yours projects? Is it straightforward which pattern you need to use?

Let take for example Service and Interactor:

> The *service* design pattern breaks down a program into its functional constituents. Each service object completes one task, such as running payment for a customer, completing a bank transaction, etc.

> You can use the *interactor* design pattern to split a large task into a series of small, inter-dependent steps. If any of the steps fail, the flow stops, and a relevant message appears about why the execution failed.

The definitions are different but the aim is the same - breaks down something big into small blocks. From my point of view, the interactor pattern is a special case of service.
```ruby
class AuthenticateUser
  include Interactor

  def call
    if user = User.authenticate(context.email, context.password)
      context.user = user
      context.token = user.secret_token
    else
      context.fail!(message: "authenticate_user.failure")
    end
  end
end
```
This excerpt was written in context of *interactor* gem.
and
```ruby
class AuthenticateUserService < BaseService
  def perform
    if (user = User.authenticate(context.email, context.password))
      success_result(status: :success, message: nil, data: user) # this method as and error_result are implemented in BaseService
    else
      error_result(status: :error, message: user.errors, data: {})
    end
  end
end
```
Does it look similar? From my perspective, they are not different patterns but one pattern with slightly different implementation.  

Let's take anther one confusing couple: _Decorator_ vs _Presenter_:

>The Decorator pattern adds new functionality to an existing object by wrapping it with additional objects containing the new features. This helps to modify an instance of a class for extra features and not define new static subclasses in the code.

>The Presenter design pattern aims to isolate view rendering logic from the controller and model and encapsulate it into a reusable component. It makes the controller and models leaner and enhances code readability.

Let's take a look into code snippets:
```ruby
class PostPresenter
  def initialize(post)
    @post = post
  end

  def image
    @post.image? ? @post.image.url : 'no-image.png'
  end
  
  # similary define other methods with their logic

end
```
```ruby
class Car
  def roof
    "fixed"
  end
end

class ConvertibleDecorator < SimpleDelegator
  def roof
    "collapsible"
  end

  def self.decorate(car)
        new(car)
  end

 private

 def model
   __getobj__
 end
end

#using 
basicCar1 = Car.new()
basicCar2 = Car.new()

basicCar1 = ConvertibleDecorator.decorate(basicCar1)

puts(basicCar1.roof) # => collapsible
puts(basicCar2.roof) # => fixed
```
You can argue that is different approach... but I would like to say - different implementation but the aim is the same. Both examples are trying to separate some additional(auxiliary) logic in separate place. And there are other way for do it, for example:
```ruby
class Car
  def roof
    "fixed"
  end
end

module ConvertibleDecorator
  def roof
    "collapsible"
  end
end

#using 
basicCar1 = Car.new()
basicCar2 = Car.new()

basicCar1 = basicCar1.extend ConvertibleDecorator

puts(basicCar1.roof) # => collapsible
puts(basicCar2.roof) # => fixed
```
Some other patterns are more straightforward and not so confusing. But the main idea of the post is:
 - try to use general principle when you structure the code (SOLID);
 - not use patterns because it is just the best practice but when you can see that it makes sense; if you cannot match you class with one of this patterns it is ok if you use something new what related to you problem (often developers see `Services` in a project and try to put all new classes there however it can be QueryObject or ValueObject).

The definitions of the patterns and part of examples were taken from [here](https://scoutapm.com/blog/rails-design-patterns#h_61620597268511623876237034)