Modelo de Rails, vista, controlador y ayudante: ¿qué va a dónde?

En Ruby on Rails Development (o MVC en general), ¿qué regla rápida debo seguir en cuanto a dónde poner la lógica?

Por favor, responda afirmativamente: con Ponga esto aquí , en lugar de No lo ponga ahí .

MVC

Controlador : coloque el código aquí que tiene que ver con averiguar qué quiere un usuario, y decidir qué darles, averiguar si están conectados, si deberían ver ciertos datos, etc. Al final, el controlador mira las solicitudes. y resuelve qué datos (Modelos) mostrar y qué Vistas mostrar. Si tiene dudas sobre si el código debería ir en el controlador, probablemente no debería. Mantenga sus controladores delgados .

Ver : la vista solo debe contener el código mínimo para mostrar sus datos (Modelo), no debe hacer mucho procesamiento o cálculo, debe mostrar datos calculados (o resumidos) por el Modelo, o generados desde el Controlador. Si su Vista realmente necesita procesar lo que no puede hacer el Modelo o el Controlador, coloque el código en un Ayudante. Un montón de código de Ruby en una vista hace que el marcado de las páginas sea difícil de leer.

Modelo : Su modelo debería estar donde vive todo su código que se relaciona con sus datos (las entidades que componen su sitio, por ejemplo, usuarios, publicaciones, cuentas, amigos, etc.). Si el código necesita guardar, actualizar o resumir datos relacionados con sus entidades, colóquelo aquí. Será reutilizable en sus Vistas y Controladores.

Para agregar a la respuesta de pauliephonic:

Ayudante : funciones para facilitar la creación de la vista. Por ejemplo, si siempre está iterando sobre una lista de widgets para mostrar su precio, colóquelo en un helper (junto con un parcial para la pantalla real). O si tiene una pieza de RJS que no quiere saturar la vista, póngala en un ayudante.

El patrón MVC solo se refiere a la interfaz de usuario y nada más. No debe poner ninguna lógica comercial compleja en el controlador, ya que controla la vista, pero no la lógica. El Controlador debería preocuparse por seleccionar la vista adecuada y delegar cosas más complejas al modelo de dominio (Modelo) o a la capa de negocios.

Domain Driven Design tiene un concepto de Servicios que es un lugar en el que se adhiere la lógica que necesita orquestar un número de varios tipos de objetos que generalmente significa lógica que no pertenece naturalmente a una clase Model.

Generalmente pienso en la capa de servicio como la API de mis aplicaciones. Las capas de Mis Servicios generalmente se corresponden bastante con los requisitos de la aplicación que estoy creando, por lo que la capa de Servicio actúa como una simplificación de las interacciones más complejas que se encuentran en los niveles inferiores de mi aplicación, es decir, se puede lograr el mismo objective pasando por alto las capas de Servicio pero tendrías que utilizar muchas más palancas para que funcione.

Tenga en cuenta que no estoy hablando de Rails aquí estoy hablando de un estilo arquitectónico general que aborda su problema particular.

Explicaciones perfectas aquí, una oración muy simple como conclusión y fácil de recordar:

Necesitamos modelos SMART, controladores THIN y vistas DUMB.

http://c2.com/cgi/wiki?ModelViewController

La manera de Rails es tener controladores flacos y modelos gordos .

Ponga cosas relacionadas con el control de autorización / acceso en el controlador.

Los modelos tienen que ver con tus datos. Validación, relaciones, CRUD, lógica de negocios

Las vistas son para mostrar sus datos. Mostrar y obtener solo entrada.

Los controladores controlan qué datos van desde su modelo hasta su vista (y qué vista) y desde su vista hasta su modelo. Los controladores también pueden existir sin modelos.

Me gusta pensar en el controlador como un guardia de seguridad / recepcionista que lo dirige al cliente (solicitud) al mostrador correspondiente donde le hace una pregunta al cajero (ver). El cajero (vista) se activa y recibe la respuesta de un gerente (modelo), a quien nunca se ve. Luego, la solicitud vuelve al guardia de seguridad / recepcionista (controlador) y espera hasta que se le indique que vaya a otro cajero (ver) que le diga la respuesta que el gerente (modelo) le respondió en respuesta a la pregunta del otro cajero (ver) .

Del mismo modo, si quiere decirle algo al cajero (ver), en gran parte sucede lo mismo, excepto que el segundo cajero le dirá si el gerente aceptó su información. También es posible que el guardia de seguridad / recepcionista (controlador) le haya dicho que realice una caminata ya que no está autorizado a decirle esa información al administrador.

Así que para extender la metáfora, en mi mundo estereotipado y poco realista, los cajeros son bonitos pero con la cabeza hueca y creen a menudo todo lo que les digas, los guardias de seguridad son mínimamente educados pero no saben mucho pero saben dónde deberían y no debería irse y los gerentes son realmente feos y malvados, pero saben todo y pueden decir qué es verdad y qué no.

Una cosa que ayuda a separar correctamente es evitar el anti patrón “pasar variables locales del controlador para ver”. En lugar de esto:

# app/controllers/foos_controller.rb: class FoosController < ApplicationController def show @foo = Foo.find(...) end end #app/views/foos/show.html.erb: ... <%= @foo.bar %> ... 

Intente moverlo a un getter disponible como método de ayuda:

 # app/controllers/foos_controller.rb: class FoosController < ApplicationController helper_method :foo def show end protected def foo @foo ||= Foo.find(...) end end #app/views/foos/show.html.erb: ... <%= foo.bar %> ... 

Esto hace que sea más fácil modificar lo que se pone en “@foo” y cómo se usa. Aumenta la separación entre el controlador y la vista sin hacerlos más complicados.

Bueno, depende de qué tiene que lidiar la lógica …

A menudo, tiene sentido insertar más elementos en sus modelos, dejando los controladores pequeños. Esto garantiza que esta lógica se pueda usar fácilmente desde cualquier lugar que necesite para acceder a los datos que representa su modelo. Las vistas deberían contener casi ninguna lógica. Entonces, en realidad, en general, debes esforzarte para que no te repitas.

Además, un poco de google revela algunos ejemplos más concretos de lo que ocurre.

Modelo: requisitos de validación, relaciones de datos, métodos de creación, métodos de actualización, métodos de destrucción, métodos de búsqueda (tenga en cuenta que no solo debe tener las versiones genéricas de estos métodos, pero si hay algo que hace mucho, como encontrar personas con rojo pelo por apellido, entonces deberías extraer esa lógica para que todo lo que tienes que hacer es llamar a find_redH_by_name (“smith”) o algo así)

Ver: esto debería ser todo sobre el formateo de datos, no el procesamiento de datos.

Controlador: aquí es donde va el procesamiento de datos. Desde Internet: “El propósito del controlador es responder a la acción solicitada por el usuario, tomar los parámetros que el usuario haya establecido, procesar los datos, interactuar con el modelo y luego pasar los datos solicitados, en su forma final, a la ver.”

Espero que ayude.

En términos simples, generalmente, los Modelos tendrán todos los códigos relacionados con la (s) tabla (s), sus relaciones simples o complejas (piensen como consultas sql que involucran múltiples tablas), la manipulación de los datos / variables para llegar a un resultado usando la lógica comercial .

Los controladores tendrán códigos / punteros hacia los modelos relevantes para el trabajo solicitado.

Las vistas aceptarán la entrada / interacción del usuario y mostrarán la respuesta resultante.

Cualquier desviación importante de estos generará tensiones no deseadas en esa parte y el rendimiento general de la aplicación puede verse afectado.

Pruebas, pruebas … Ponga tanta lógica como sea posible en el modelo y luego podrá probarla correctamente. Las pruebas unitarias prueban los datos y la forma en que se forman probando el modelo, y las pruebas funcionales prueban la forma en que se enruta o controla probando los controladores, por lo que se deduce que no se puede probar la integridad de los datos a menos que sea el modelo.

j