Debido a que Rails proporciona una estructura en términos de MVC, es natural terminar usando solo los contenedores de modelo, vista y controlador que se proporcionan para usted. El idioma típico para principiantes (e incluso algunos programadores intermedios) es incluir toda la lógica de la aplicación en el modelo (clase de base de datos), controlador o vista.
En algún momento, alguien señala el paradigma "modelo gordo, controlador delgado", y los desarrolladores intermedios eliminan rápidamente todo de sus controladores y lo tiran al modelo, que comienza a convertirse en un nuevo bote de basura para la lógica de la aplicación.
Los controladores flacos son, de hecho, una buena idea, pero el corolario: poner todo en el modelo, no es realmente el mejor plan.
En Ruby, tienes un par de buenas opciones para hacer las cosas más modulares. Una respuesta bastante popular es simplemente usar módulos (generalmente escondidos lib
) que contienen grupos de métodos, y luego incluir los módulos en las clases apropiadas. Esto ayuda en los casos en los que tiene categorías de funcionalidad que desea reutilizar en varias clases, pero donde la funcionalidad todavía está vinculada a las clases.
Recuerde, cuando incluye un módulo en una clase, los métodos se convierten en métodos de instancia de la clase, por lo que aún termina con una clase que contiene una tonelada de métodos, simplemente se organizan muy bien en varios archivos.
Esta solución puede funcionar bien en algunos casos; en otros casos, querrá pensar en usar clases en su código que no sean modelos, vistas o controladores.
Una buena manera de pensarlo es el "principio de responsabilidad única", que dice que una clase debería ser responsable de una sola (o pequeña cantidad) de cosas. Sus modelos son responsables de los datos persistentes de su aplicación a la base de datos. Sus controladores son responsables de recibir una solicitud y devolver una respuesta viable.
Si tiene conceptos que no encajan perfectamente en las cajas (persistencia, la petición / respuesta de gestión), es probable que quiera pensar acerca de cómo se podría modelar la idea de que se trate. Puede almacenar clases que no sean modelos en la aplicación / clases, o en cualquier otro lugar, y agregar ese directorio a su ruta de carga haciendo lo siguiente:
config.load_paths << File.join(Rails.root, "app", "classes")
Si está utilizando pasajero o JRuby, probablemente también desee agregar su ruta a las rutas de carga ansiosas:
config.eager_load_paths << File.join(Rails.root, "app", "classes")
La conclusión es que una vez que llegas a un punto en Rails donde te encuentras haciendo esta pregunta, es hora de reforzar tus habilidades de Ruby y comenzar a modelar clases que no son solo las clases MVC que Rails te da por defecto.
Actualización: esta respuesta se aplica a Rails 2.xy superior.
Actualización : El uso de Preocupaciones se ha confirmado como el nuevo valor predeterminado en Rails 4 .
Realmente depende de la naturaleza del módulo en sí. Por lo general, coloco extensiones de controlador / modelo en una carpeta / preocupaciones dentro de la aplicación.
/ lib es mi opción preferida para bibliotecas de uso general. Siempre tengo un espacio de nombres de proyecto en lib donde pongo todas las bibliotecas específicas de la aplicación.
Las extensiones de núcleo de Ruby / Rails generalmente tienen lugar en los inicializadores de configuración para que las bibliotecas solo se carguen una vez en el arranque de Rails.
Para fragmentos de código reutilizables, a menudo creo (micro) complementos para poder reutilizarlos en otros proyectos.
Los archivos de ayuda generalmente contienen métodos de ayuda y, a veces, clases cuando el objeto está destinado a ser usado por los ayudantes (por ejemplo, los Constructores de formularios).
Esta es una visión general muy general. Proporcione más detalles sobre ejemplos específicos si desea obtener sugerencias más personalizadas. :)
fuente
"enorme" es una palabra preocupante ... ;-)
¿Cómo se están volviendo enormes tus controladores? Eso es algo que debe mirar: idealmente, los controladores deben ser delgados. Escogiendo una regla general de la nada, sugeriría que si regularmente tiene más de, por ejemplo, 5 o 6 líneas de código por método de controlador (acción), entonces sus controladores probablemente sean demasiado gordos. ¿Hay duplicación que podría pasar a una función auxiliar o un filtro? ¿Existe una lógica de negocios que pueda ser introducida en los modelos?
¿Cómo llegan a ser enormes tus modelos? ¿Debería buscar formas de reducir el número de responsabilidades en cada clase? ¿Hay algún comportamiento común que puedas extraer en mixins? ¿O áreas de funcionalidad que puede delegar en clases auxiliares?
EDITAR: tratando de expandirse un poco, con suerte no distorsionar nada demasiado ...
Ayudantes: viven
app/helpers
y se utilizan principalmente para simplificar las vistas. Son específicos del controlador (también disponibles para todas las vistas para ese controlador) o generalmente disponibles (module ApplicationHelper
en application_helper.rb).Filtros: supongamos que tiene la misma línea de código en varias acciones (con bastante frecuencia, recuperación de un objeto usando
params[:id]
o similar). Esa duplicación se puede abstraer primero a un método separado y luego fuera de las acciones por completo declarando un filtro en la definición de clase, comobefore_filter :get_object
. Consulte la Sección 6 de la Guía de rieles de ActionController. Deje que la programación declarativa sea su amiga.Refactorizar modelos es algo más religioso. Los discípulos del tío Bob sugerirán, por ejemplo, que sigas los cinco mandamientos de SOLID . Joel y Jeff pueden recomendar un enfoque más, "pragmático", aunque posteriormente parecieron un poco más reconciliados . Encontrar uno o más métodos dentro de una clase que operan en un subconjunto claramente definido de sus atributos es una forma de tratar de identificar las clases que podrían reestructurarse a partir de su modelo derivado de ActiveRecord.
Los modelos Rails no tienen que ser subclases de ActiveRecord :: Base, por cierto. O para decirlo de otra manera, un modelo no tiene que ser un análogo de una tabla, o incluso estar relacionado con algo almacenado. Aún mejor, siempre que nombre su archivo de
app/models
acuerdo con las convenciones de Rails (llame a #underscore en el nombre de la clase para averiguar qué buscará Rails), Rails lo encontrará sin querequire
sea necesario.fuente
Aquí hay una excelente publicación de blog sobre refactorizar los modelos gordos que parecen surgir de la filosofía del "controlador delgado":
http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/
El mensaje básico es "No extraiga mixinas de modelos gordos", use clases de servicio en su lugar, el autor proporciona 7 patrones para hacerlo
fuente