2009-01-01 6 views
28

Es una buena práctica cambiar la lógica del controlador al modelo. Pero en cualquier sistema complejo, esto conduce invariablemente a un archivo muy grande, incluso si la mayoría de los métodos son de una sola línea según Rails Way.¿Cómo organizar los modelos de Rails demasiado gordos?

He recurrido a dividir los modelos en otros módulos e incluirlos en el modelo original, por ejemplo, model_flags, model_validation, etc. ¿Alguien tiene una manera mejor?

Editar: He seleccionado una nueva respuesta que sugiere el uso de ActiveConcern. Además, para cualquier persona que esté interesada en organizar el código, este artículo, Making ActiveRecord Models Thin, debería ser de gran ayuda.

Respuesta

28

Me di cuenta de esto es una pregunta bastante antigua y ha sido marcada como respondida, pero todavía tiene un buen jugo de Google, así que pensé que valía la pena agregar a ...

Rails 3 presentó ActiveSupport :: Concern, que se puede usar para modularizar el comportamiento eso se comparte entre los modelos. O, para el caso, adelgazar modelos que se han vuelto demasiado gordos.

DHH mismo proporciona un agradable, sucinta ejemplo GIST aquí:

https://gist.github.com/1014971

+1

Aprendí sobre esto de la Red Dot Ruby Conference (creo por Gregg Polack), así que sí, creo que de ahora en adelante, esta es una mejor manera, que juega muy bien con el núcleo de los rieles. – Jaryl

+0

Una nota: la terminología (del asunto, no la respuesta) terminó siendo confusa. 'ActiveSupport :: Concern' se usa para escribir modelos con código reutilizable (en muchos modelos) mientras que el patrón' concerned_with' es una forma simple de dividir un modelo en partes. Me gusta el primero (porque me indica usar la aplicación/en lugar de lib /) y no estoy seguro del segundo (parece conveniente pero conceptualmente dudoso). – tokland

+2

Creo que vale la pena señalar que las preocupaciones son solo una forma de abordar la obesidad modelo. Como notas srboisvert, es una buena idea cuestionar el diseño de su objeto antes de elegir dividir un modelo en preocupaciones. Aquí hay un artículo que analiza eso: http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/ – tjstankus

0

Los módulos suena sensato. No extraería las llamadas a métodos (validaciones, devoluciones de llamada, complementos, etc.) en módulos, sin embargo, limitaría la extracción a mis propios métodos.

Y, como siempre, sería útil si publicara algún código de muestra. Me resulta difícil imaginar una estrategia genérica para limpiar modelos, depende de la naturaleza del código.

+0

Bueno, esa es la cosa; Realmente no tengo una estrategia. Actualmente, simplemente estoy descargando métodos de un archivo a otro, lo que no me parece muy oportuno, y por eso estoy aquí para descubrir cuál es la mejor práctica. Cheers =) – Jaryl

5

No haría esto por algunas razones.

Primero viola la suposición de que las cosas estarán donde deberían estar, lo cual es probablemente la mayor ventaja para los rieles en primer lugar. Una nueva persona puede caminar sobre su proyecto y navegarlo con bastante facilidad si pega material modelo en su modelo. Si lo saca, solo agrega un retraso y algo de confusión, especialmente si la única lógica para eliminar algo de un módulo es reducir el tamaño del modelo.

Segundo, no ganas casi nada y pierdes algo. El tamaño del archivo no importa en estos días cuando casi todos los editores e IDE alivian el dolor de navegación de los archivos de gran tamaño. Mover cosas a un módulo en realidad quita parte de esta facilidad moderna y requerirá que usted y sus colegas o futuros mantenedores salten varios archivos más mientras trabajan en un modelo.

Dicho esto, sospecho que lo que la mejor práctica de los rieles duros le dirá es que si su modelo es tan grande y complejo, su diseño es defectuoso y su modelo probablemente represente varias cosas que podrían convertirse en modelos separados en lugar de módulos.

+1

La mayor parte del comportamiento en Rails no se puede encontrar "donde deberían estar". Además, al incluir módulos en el archivo de modelo principal, ya le está diciendo a otros dónde buscar. Acepto que navegar por archivos grandes no es tan difícil, pero ¿cómo se dividen sus modelos? ¿Qué tipo de métodos van primero? – Jaryl

+0

No dividir mis modelos. Vacilo entre organizarlos por funcionalidad y alfabéticamente, pero realmente no me preocupo demasiado por eso. Estoy de acuerdo con nakajima en que debe extraer la funcionalidad compartida y reutilizable donde sea posible, pero más por el bien de DRY y un buen diseño que la longitud. – srboisvert

+0

Como observo en un comentario a mi propia respuesta, creo que este es un punto válido, particularmente el último párrafo. No hay nada cortado y seco cuando se trata de diseño de objetos. Cuestiona tus diseños a menudo y haz tu mejor juicio. – tjstankus

1

No tener conocimiento de su modelo de objeto, es un poco más difícil de aconsejar, pero diría que si está absolutamente convencido de que todas las validaciones/asociaciones/devoluciones de llamada necesitan para estar en ese lugar, hay todavía hay maneras de factorizar comportamientos comunes. Entonces, si bien no solo movería una gran porción de código de un archivo a otro, sino que volvería a abrir la clase, diría que es una buena idea usar módulos/complementos para describir los tipos comunes de comportamientos.

Por ejemplo, si está creando un feed de actividad de Facebook, y todo tiene que generar "eventos", entonces quizás desee mover ese comportamiento "Evitable" a un módulo, que cuando se incluye, define las asociaciones/validaciones/etc. Diría que ese enfoque en realidad mejoraría la claridad de tu código, ya que especificar manualmente esas asociaciones en todas partes no es tan expresivo como declarar algo como Evitable, ni tampoco es tan seguro (estarías duplicando la lógica en un montón de lugares , y cuando la lógica cambia, usted sabe el resto ...)

En general, yo diría que eche un vistazo a su modelo de objetos. En su suite de pruebas, si observa que todas sus pruebas requieren mucha configuración, puede ser un buen indicador de que le falta algo en su modelo de objetos. De nuevo, un código de muestra sería genial.

Cuestiones relacionadas