Evoluindo nosso Projeto Rails: Integrando o Padrão Factory para Maior Flexibilidade e Organização
Rodrigo Barreto
Posted on January 12, 2024
No meu post anterior Os benefícios de usar Form Objects em seus projetos, discutimos os benefícios significativos de utilizar Form Objects em projetos Ruby on Rails, usando um sistema de reserva de eventos como exemplo.
O padrão Factory é benéfico para situações onde você tem várias subclasses ou tipos de objetos similares e quer abstrair a lógica de criação desses objetos. Ele é útil para manter o código organizado e fácil de manter, especialmente quando há necessidade de adicionar novos tipos de objetos no futuro. O Factory permite centralizar a criação de objetos, facilitando mudanças e expandindo a aplicação sem grandes alterações na base de código existente. É ideal para projetos que requerem flexibilidade e escalabilidade na gestão de diferentes instâncias de objetos.
Continuando nossa jornada para aprimorar ainda mais essa aplicação, neste post, exploraremos como a integração do padrão Factory pode trazer uma nova dimensão de flexibilidade e eficiência. Ao expandir nosso sistema para incluir um novo tipo de evento - o concert
- veremos como o Factory nos permite gerenciar a crescente complexidade de forma mais elegante, mantendo nosso código enxuto e facilmente expansível. Vamos mergulhar nos detalhes de como essa abordagem pode ser um divisor de águas na otimização e escalabilidade de nossos projetos Rails.
Imagine a situação em que o nosso gerente de produto nos pede para adicionar um novo tipo de evento, o concerto (concert), ao nosso sistema nesta semana. Além disso, ele nos alerta que em breve surgirão mais tipos de eventos, como casamento (wedding) e outros.
Portanto, é crucial que preparemos a estrutura de eventos de forma que possa ser facilmente escalada. Isso envolve criar um sistema onde a adição de novos tipos de eventos possa ser feita de maneira simples e eficiente, garantindo a flexibilidade e a adaptabilidade do nosso projeto às futuras demandas e necessidades.
Agora, vamos avançar na construção do nosso sistema, criando um novo objeto de formulário: EventConcertForm. Este formulário será específico para lidar com as características e validações únicas de eventos do tipo "concert". Implementar esse formulário é um passo importante para expandir a capacidade da nossa aplicação de gerenciar diferentes tipos de eventos de forma eficiente e organizada.
No EventConcertForm, aplicaremos uma regra específica: é necessário que o evento tenha um número de participantes maior que 100
. Essa validação simples assegura que os eventos do tipo "concert" sejam apropriados para um grande público, o que é uma característica comum deste tipo de evento. A implementação dessa regra no formulário ajudará a manter a consistência e a relevância dos dados de eventos do tipo "concert" na nossa aplicação.
# frozen_string_literal: true
module Events
class EventConcertForm < Events::EventFormBase
validates :number_of_people, numericality: { greater_than: 100 }
end
end
No nosso projeto Rails, fizemos uma atualização no EventFormBase.rb, introduzindo um novo método create. Esse método valida e cria um evento diretamente dentro do formulário, exemplificando uma abordagem mais modular e organizada no manejo de dados. Essa mudança reflete nosso compromisso com a eficiência e a clareza no desenvolvimento da aplicação.
# frozen_string_literal: true
module Events
class EventFormBase
include ActiveModel::Model
attr_accessor :title, :description, :event_type, :number_of_people, :special_requests
validates :title, :event_type, :number_of_people, presence: true
def attributes
{
title:,
description:,
event_type:,
number_of_people:,
special_requests:
}
end
def create
return false unless valid?
event = Event.new(attributes)
event.save!
end
end
end
Na estrutura criada a BaseFactory
serve como um molde para as Factories(Fábricas), definindo um método de classe call
que instancia e chama um método call no objeto criado. Este método call deve ser implementado nas subclasses concretas. Já a EventFactory
é uma implementação específica da BaseFactory, onde definimos um método initialize para configurar a ação e os parâmetros e um método call que seleciona e instancia o formulário de evento apropriado com base na ação fornecida. Isso facilita a criação flexível e dinâmica de diferentes tipos de formulários de eventos, como "birthday", "business" e "concert", com base nos parâmetros recebidos.
class BaseFactory
class << self
def call(...)
new(...).call
end
end
def call
raise NotImplementedError, "'#{__method__}' should be implemented in concrete class"
end
end
# frozen_string_literal: true
class EventFactory < BaseFactory
class InvalidEventTypeError < StandardError; end
attr_accessor :action, :params
def initialize(action:, params:)
@action = action
@params = params
end
def call
action_service = events[action]
raise InvalidEventTypeError unless action_service
action_service.new(**params)
end
private
def events
{
"birthday": Events::EventBirthdayForm,
"business": Events::EventBusinessForm,
"concert": Events::EventConcertForm,
}
end
end
Com a introdução da EventFactory
, o EventsController
será refinado para uma abordagem mais limpa e eficiente. Essa mudança não só melhora a clareza do código, mas também facilita a inclusão de novos tipos de eventos.
# frozen_string_literal: true
module Api
module V1
class EventsController < ApplicationController
def create
form = EventFactory.call(action: event_params[:event_type].to_sym, params: event_params)
if form.create
render json: form, status: :created
else
render json: form.errors, status: :unprocessable_entity
end
rescue EventFactory::InvalidEventTypeError => e
render json: { error: e.message }, status: :bad_request
end
private
def event_params
params.require(:event).permit(:title, :description, :event_type, :number_of_people, :special_requests)
end
end
end
end
O EventsController
agora está mais enxuto e organizado, com a eliminação dos métodos create_event
e build_event_form
. A introdução da EventFactory
permite que as responsabilidades de criação de formulários de eventos sejam separadas de forma mais eficiente, substituindo o antigo build_event_form
. Essa mudança demonstra um uso eficaz do padrão Factory, realçando a clareza e a modularidade do código em nosso projeto Rails.
Se você estiver interessado em testar o código, pode fazer isso clonando o projeto na branch factory_pattern do repositório no GitHub. Acesse factory_pattern para ir diretamente à branch específica e explorar como o padrão Factory foi implementado no sistema de reserva de eventos.
Posted on January 12, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.