Como o Rails fornece estrutura em termos de MVC, é natural acabar usando apenas o modelo, a exibição e os contêineres de controlador que são fornecidos para você. O idioma típico para iniciantes (e até alguns programadores intermediários) é incluir toda a lógica do aplicativo no modelo (classe de banco de dados), controlador ou exibição.
Em algum momento, alguém aponta o paradigma "modelo gordo, controlador fino" e os desenvolvedores intermediários rapidamente tiram tudo de seus controladores e jogam no modelo, que começa a se tornar uma nova lixeira para a lógica de aplicativos.
Controladores magros são, de fato, uma boa idéia, mas o corolário - colocar tudo no modelo, não é realmente o melhor plano.
No Ruby, você tem algumas boas opções para tornar as coisas mais modulares. Uma resposta bastante popular é usar apenas módulos (geralmente escondidos lib
) que contêm grupos de métodos e depois incluí-los nas classes apropriadas. Isso ajuda nos casos em que você tem categorias de funcionalidade que deseja reutilizar em várias classes, mas onde a funcionalidade ainda está nocionalmente anexada às classes.
Lembre-se, quando você incluir um módulo em uma classe, os métodos tornam-se métodos de instância da classe, para que você ainda acabar com uma classe que contém uma tonelada de métodos, eles estão apenas organizou muito bem em vários arquivos.
Essa solução pode funcionar bem em alguns casos - em outros casos, você vai querer pensar em usar classes em seu código que não sejam modelos, visualizações ou controladores.
Uma boa maneira de pensar sobre isso é o "princípio de responsabilidade única", que diz que uma classe deve ser responsável por um único (ou pequeno número) de coisas. Seus modelos são responsáveis pela persistência de dados do seu aplicativo no banco de dados. Seus controladores são responsáveis por receber uma solicitação e retornar uma resposta viável.
Se você tem conceitos que não se encaixam perfeitamente em essas caixas (persistência, pedido / resposta de gestão), você provavelmente vai querer pensar sobre como você seria modelar a idéia em questão. Você pode armazenar classes não modelo em app / classes ou em qualquer outro lugar e adicionar esse diretório ao seu caminho de carregamento, fazendo:
config.load_paths << File.join(Rails.root, "app", "classes")
Se você estiver usando passageiro ou JRuby, provavelmente também desejará adicionar seu caminho aos caminhos de carga ansiosos:
config.eager_load_paths << File.join(Rails.root, "app", "classes")
O ponto principal é que, quando você chega a um ponto no Rails em que se pergunta: é hora de reforçar seus chops Ruby e começar a modelar classes que não são apenas as classes MVC que o Rails fornece por padrão.
Atualização: Esta resposta se aplica ao Rails 2.xe superior.
Atualização : O uso de preocupações foi confirmado como o novo padrão no Rails 4 .
Realmente depende da natureza do próprio módulo. Normalmente, coloco extensões de controlador / modelo em uma pasta / preocupações dentro do aplicativo.
/ lib é minha escolha preferida para bibliotecas de uso geral. Eu sempre tenho um espaço para nome do projeto na lib, onde coloco todas as bibliotecas específicas do aplicativo.
As extensões principais do Ruby / Rails geralmente ocorrem nos inicializadores de configuração, para que as bibliotecas sejam carregadas apenas uma vez no boostrap do Rails.
Para fragmentos de código reutilizáveis, geralmente crio (micro) plugins para poder reutilizá-los em outros projetos.
Os arquivos auxiliares geralmente contêm métodos auxiliares e às vezes classes quando o objeto se destina a ser usado por auxiliares (por exemplo, Construtores de formulários).
Esta é uma visão geral realmente geral. Forneça mais detalhes sobre exemplos específicos se desejar obter sugestões mais personalizadas. :)
fonte
"enorme" é uma palavra preocupante ... ;-)
Como seus controladores estão se tornando enormes? É algo que você deve considerar: idealmente, os controladores devem ser finos. Escolhendo uma regra geral do nada, sugiro que se você tiver regularmente mais de, digamos, 5 ou 6 linhas de código por método de controlador (ação), seus controladores provavelmente serão gordos demais. Existe duplicação que poderia passar para uma função auxiliar ou um filtro? Existe lógica de negócios que poderia ser introduzida nos modelos?
Como seus modelos são enormes? Você deve procurar maneiras de reduzir o número de responsabilidades em cada classe? Existem comportamentos comuns que você pode extrair em mixins? Ou áreas de funcionalidade que você pode delegar para as classes auxiliares?
EDIT: Tentando expandir um pouco, espero não distorcer nada muito mal ...
Ajudantes: moram
app/helpers
e são usados principalmente para simplificar as visualizações. Eles são específicos do controlador (também disponíveis para todas as visualizações desse controlador) ou geralmente estão disponíveis (module ApplicationHelper
em application_helper.rb).Filtros: digamos que você tenha a mesma linha de código em várias ações (muitas vezes, recuperação de um objeto usando
params[:id]
ou similar). Essa duplicação pode ser abstraída primeiro para um método separado e, em seguida, para fora das ações, declarando um filtro na definição de classe, comobefore_filter :get_object
. Veja a Seção 6 no Guia ActionController Rails Deixe a programação declarativa ser sua amiga.Refatorar modelos é um pouco mais religioso. Os discípulos do tio Bob sugerem, por exemplo, que você siga os cinco mandamentos do SOLID . Joel & Jeff podem recomendar uma abordagem mais, mais "pragmática", embora pareçam ser um pouco mais reconciliados posteriormente. Encontrar um ou mais métodos dentro de uma classe que operam em um subconjunto claramente definido de seus atributos é uma maneira de tentar identificar classes que podem ser refatoradas fora do seu modelo derivado do ActiveRecord.
Os modelos Rails não precisam ser subclasses de ActiveRecord :: Base, a propósito. Ou, dito de outra forma, um modelo não precisa ser um análogo de uma tabela ou mesmo relacionado a qualquer coisa armazenada. Melhor ainda, desde que você nomeie seu arquivo de
app/models
acordo com as convenções do Rails (chame #underscore no nome da classe para descobrir o que o Rails procurará), o Rails o encontrará sem querequire
seja necessário.fonte
Aqui está um excelente post sobre refatoração dos modelos de gordura que parecem surgir da filosofia do "controlador fino":
http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/
A mensagem básica é "Não extrair mixins de modelos de gordura"; use classes de serviço; o autor fornece 7 padrões para fazer isso.
fonte