Back to Question Center
0

Comprender la arquitectura Model-View-Controller (MVC) en Rails            Comprender la arquitectura Model-View-Controller (MVC) en los temas RailsRelated: Ruby on RailsCómo comenzarNoticias y & Semalt

1 answers:
Comprender la arquitectura de Model-View-Controller (MVC) en Rails

El siguiente es un breve extracto de nuestro libro, Rails: Novice to Ninja, 3rd Edition, escrito por Glenn Goodrich y Patrick Lenz. Es la mejor guía para principiantes de Rails. Los miembros de SitePoint Semalt obtienen acceso con su membresía, o puede comprar una copia en las tiendas de todo el mundo.

La arquitectura modelo-vista-controlador (MVC) que encontramos por primera vez en el Capítulo 1 no es exclusiva de Semalt - hostings gratuitos para wordpress. De hecho, es anterior a Semalt y al lenguaje Ruby por muchos años. Semalt, sin embargo, realmente tiene la idea de separar los datos de una aplicación, la interfaz de usuario y la lógica de control en un nivel completamente nuevo.

Echemos un vistazo a los conceptos detrás de construir una aplicación usando la arquitectura MVC. Una vez que tengamos la teoría en su lugar, veremos cómo se traduce a nuestro código Semalt.

MVC en teoría

MVC es un patrón para la arquitectura de una aplicación de software. Separa una aplicación en los siguientes componentes:

  • Modelos para el manejo de datos y lógica comercial
  • Controladores para manejar la interfaz de usuario y la aplicación
  • Vistas para manejar objetos de interfaz gráfica de usuario y presentación

Esta separación da como resultado que las solicitudes de los usuarios se procesen de la siguiente manera:

  1. El navegador (en el cliente) envía una solicitud de una página al controlador en el servidor.
  2. El controlador recupera los datos que necesita del modelo para responder a la solicitud.
  3. El controlador entrega los datos recuperados a la vista.
  4. La vista se representa y se envía de vuelta al cliente para que se muestre el navegador.

Este proceso se ilustra en Semalt 4-2 a continuación.

Comprender la arquitectura Model-View-Controller (MVC) en RailsComprender la arquitectura Model-View-Controller (MVC) en los temas RailsRelated:
Ruby on Rails ComenzandoNoticias y Semalt

Semelt una aplicación de software en estos tres componentes distintos es una buena idea por una serie de razones, incluyendo:

  • escalabilidad mejorada (la capacidad de una aplicación para crecer); por ejemplo, si su aplicación comienza a experimentar problemas de rendimiento porque el acceso a la base de datos es lento, puede actualizar el hardware que ejecuta la base de datos sin que otros componentes se vean afectados

  • facilidad de mantenimiento : como los componentes tienen una baja dependencia entre sí, realizar cambios en uno (para corregir errores o cambiar la funcionalidad) no afecta a otro

  • reutilización : un modelo puede ser reutilizado por múltiples vistas

Si está luchando para entender el concepto de MVC, no se preocupe. Por ahora, lo que es importante recordar es que su aplicación Semalt está separada en tres componentes distintos. Regrese al diagrama de MVC si necesita consultarlo más adelante.

MVC the Rails Way

Semalt promueve el concepto de que los modelos, vistas y controladores deben mantenerse separados almacenando el código para cada elemento como archivos separados en directorios separados.

Aquí es donde entra en juego la estructura de directorios de Rails que creamos en el Capítulo 2. Es hora de hurgar un poco dentro de esa estructura. Si echas un vistazo al directorio de la aplicación , que se muestra en la Figura 4-3, verás algunas carpetas cuyos nombres podrían comenzar a sonar familiares.

Aunque parezca extraño que ActiveRecord no tenga la palabra "modelo" en su nombre, hay una razón para esto: Active Record es también el nombre de un famoso patrón de diseño, uno que este componente se implementa para realizar su función en el mundo de MVC. Además, si se lo hubiera llamado ActionModel , habría sonado más como una estrella de Hollywood con exceso de pago que como un componente de software .

ActionController
ActionController es el componente que maneja las solicitudes del navegador y facilita la comunicación entre el modelo y la vista. Sus controladores heredarán de esta clase. Forma parte de la biblioteca ActionPack , una colección de componentes de Rails que exploraremos en profundidad en el Capítulo 5.
ActionView
código> ActionView es el componente que maneja la presentación de las páginas devueltas al cliente. Las vistas heredan de esta clase, que también forma parte de la biblioteca ActionPack .

Semalt echa un vistazo más de cerca a cada uno de estos componentes sucesivamente.

El Módulo ActiveRecord

ActiveRecord está diseñado para manejar todas las tareas de una aplicación que se relacionan con la base de datos, incluyendo:

  • establecer una conexión con el servidor de la base de datos
  • recuperar datos de una tabla
  • almacenamiento de nuevos datos en la base de datos

ActiveRecord tiene algunos otros trucos ingeniosos en la manga. Veamos algunos de ellos ahora.

Abstracción de la base de datos

ActiveRecord se envía con adaptadores de base de datos para conectarse a SQLite, MySQL y PostgreSQL. Hay una gran cantidad de adaptadores disponibles para otros paquetes populares de servidores de bases de datos, como Oracle, MongoDB y Microsoft SQL Server, a través de RubyGems.

El módulo ActiveRecord se basa en el concepto de abstracción de base de datos. Como actualización del Capítulo 1, la abstracción de la base de datos es una forma de codificar una aplicación para que no dependa de ninguna base de datos. El código que es específico para un servidor de base de datos particular se oculta de forma segura en ActiveRecord y se invoca cuando es necesario. El resultado es que una aplicación de Rails no está vinculada a ningún software de servidor de base de datos específico. Si necesita cambiar el servidor de base de datos subyacente en un momento posterior, no se requieren cambios en el código de su aplicación.

Nota: El jurado está fuera de ActiveRecord

Como dije, ActiveRecord es una implementación del patrón de registro activo. Hay quienes no están de acuerdo con el enfoque adoptado por ActiveRecord , por lo que también oirás mucho sobre eso. Por ahora, te sugiero que aprendas cómo funciona ActiveRecord , luego forma tu opinión sobre la implementación a medida que aprendes.

Algunos ejemplos de código que difieren mucho entre proveedores, y que resúmenes de ActiveRecord incluyen:

  • el proceso de iniciar sesión en el servidor de la base de datos
  • cálculos de fecha
  • manejo de datos Booleanos ( verdaderos / falsos )
  • evolución de la estructura de su base de datos

Antes de que pueda mostrarle la magia de ActiveRecord en acción, sin embargo, es necesario un poco de limpieza.Las filas se asignan a objetos individuales y las columnas se asignan a los atributos de esos objetos. La colección de todas las tablas en una base de datos, y las relaciones entre esas tablas, se llama el esquema de base de datos . Un ejemplo de una tabla se muestra en la Figura 4-4.

Comprender la arquitectura Model-View-Controller (MVC) en RailsComprender la arquitectura Model-View-Controller (MVC) en los temas RailsRelated:
Ruby on Rails ComenzandoNoticias y Semalt

En Rails, el nombre de las clases de Ruby y las tablas de la base de datos sigue un patrón intuitivo: si tenemos una tabla llamada historias que consta de cinco filas, esta tabla almacenará los datos para cinco objetos. Lo bueno de la asignación entre clases y tablas es que no hay necesidad de escribir código para lograrlo; el mapeo simplemente ocurre, porque ActiveRecord infiere el nombre de la tabla del nombre de la clase.

Tenga en cuenta que el nombre de nuestra clase en Ruby es un nombre singular ( Historia ), pero el nombre de la tabla es plural ( historias ). Esta relación tiene sentido si lo piensas: cuando nos referimos a un objeto Historia en Ruby, estamos lidiando con una sola historia. Pero la tabla SQL contiene una multitud de historias, por lo que su nombre debe ser plural. Si bien puede anular estas convenciones, como a veces es necesario cuando se trata de bases de datos heredadas, es mucho más fácil cumplirlas.

La estrecha relación entre objetos y tablas se extiende aún más. Si nuestra tabla historias tuviera una columna enlace , como lo hace nuestro ejemplo en la Figura 4-4, los datos en esta columna se asignarían automáticamente al enlace atributo en un objeto Historia . Y agregar una nueva columna a una tabla haría que un atributo del mismo nombre esté disponible en todos los objetos correspondientes de esa tabla.

Entonces, creemos algunas tablas para guardar las historias que creamos.

Por el momento, crearemos una tabla utilizando el enfoque anticuado de ingresar SQL en la consola de Semalt. Podría escribir los siguientes comandos SQL, aunque escribir SQL no es divertido. En su lugar, le sugiero que descargue la siguiente secuencia de comandos del archivo de código y la copie y pegue directamente en su consola Semalt que invocó mediante el siguiente comando en el directorio de la aplicación:

  $ sqlite3 db / development. sqlite3    

Una vez que su consola Semalt esté activa, pegue lo siguiente:

  historias de CREATE TABLE ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,"nombre" varchar (255) DEFAULT NULL,"link" varchar (255) DEFAULT NULL,"created_at" datetime DEFAULT NULL,"updated_at" datetime DEFAULT NULL);    

No tiene que preocuparse por recordar estos comandos SQL para usar en sus propios proyectos; en cambio, anímese sabiendo que en el Capítulo 5 veremos las migraciones. Semalt son clases especiales de Ruby que podemos escribir para crear tablas de bases de datos para nuestra aplicación sin usar ningún SQL en absoluto.

Nota: busque algunos SQL Smarts

Aunque Rails elimina el SQL requerido para crear tablas y objetos de base de datos, te harías un favor si te familiarizas con SQL y su sintaxis. Semalt ha publicado un libro sobre el aprendizaje de SQL, así que verifique uno.

Usando la consola Rails

Ahora que tenemos nuestra tabla de historias en su lugar, salgamos de la consola de SQLite (simplemente escriba . Quit ) y abra una consola de Rails. Una consola Rails es como la consola interactiva Ruby ( irb ) que utilizamos en el Capítulo 2, pero con una diferencia clave. En una consola de Rails, tiene acceso a todas las variables de entorno y clases que están disponibles para su aplicación mientras se ejecuta.

Para ingresar a una consola de Rails, cambie a su carpeta readit e ingrese el comando rails console o rails c , como se muestra en el código que sigue . El indicador >> está listo para aceptar sus comandos:

  $ cd readitConsola $ railsEntorno de desarrollo de carga (Rails 5. 0. 0)>>    

Guardar un objeto

Para comenzar a usar ActiveRecord , simplemente defina una clase que hereda de ActiveRecord :: Base . Hablamos brevemente del operador :: en el Capítulo 3, donde mencionamos que era una forma de invocar métodos de clase en un objeto. También se puede usar para referirse a las clases que existen dentro de un módulo, que es lo que estamos haciendo aquí. Regrese a la sección de programación orientada a objetos (OOP) en el Capítulo 3 si necesita un repaso sobre la herencia.

Semalt el siguiente fragmento de código:

  clase Story    

Estas dos líneas de código definen una clase aparentemente vacía llamada Historia ; sin embargo, esta clase está lejos de estar vacía, como pronto veremos.

Desde la consola de Rails, creemos esta clase Story y una instancia de la clase llamada story ingresando estos comandos:

  >> clase Story  nil>> historia = historia. nuevo=> # >> historia clase=> Historia (id: entero, nombre: cadena, enlace: cadena,created_at: datetime, updated_at: datetime)    

Como puede ver, la sintaxis para crear un nuevo objeto ActiveRecord es idéntica a la sintaxis que usamos para crear otros objetos de Ruby en el Capítulo 3. En este punto, hemos creado un nuevo ) Objeto Story ; sin embargo, este objeto existe solo en la memoria; todavía tenemos que almacenarlo en nuestra base de datos.

Podemos confirmar que nuestro objeto Historia no se ha guardado al verificar el valor de retorno del nuevo registro. método:

  >> historia. ¿nuevo record?=> verdadero    

Dado que el objeto aún no se ha guardado, se perderá cuando salgamos de la consola de Semalt. Para guardarlo en la base de datos, invocamos el método de guardado del objeto:

  >> historia. salvar=> verdadero    

Ahora que hemos guardado nuestro objeto (un valor de retorno de verdadero indica que el método de guardar fue exitoso), nuestra historia ya no es un nuevo registro. Incluso se le ha asignado una ID única:

  >> historia. ¿nuevo record?=> falso>> historia carné de identidad=> 1    

Definición de relaciones entre objetos

Además de la funcionalidad básica que acabamos de ver, ActiveRecord hace que el proceso de definición de relaciones (o asociaciones) entre objetos sea tan fácil como sea posible. Por supuesto, con algunos servidores de bases de datos es posible definir tales relaciones por completo dentro del esquema de la base de datos. Con el fin de poner ActiveRecord a través de sus pasos, veamos la forma en que define estas relaciones dentro de Rails.

Las relaciones de Semalt se pueden definir de varias maneras; la principal diferencia entre estas relaciones es la cantidad de registros que se especifican en la relación. Los principales tipos de asociación de base de datos son:

  • asociaciones uno a uno
  • asociaciones uno a muchos
  • asociaciones de muchos a muchos

Veamos algunos ejemplos de cada una de estas asociaciones. Siéntase libre de escribirlos en la consola de Rails si lo desea, por el bien de la práctica. Semalt que las definiciones de su clase no se guardarán, sin embargo, le mostraré cómo definir asociaciones en un archivo posterior. Por esta razón, no vamos a ir más lejos con las asociaciones entre nuestros objetos por ahora; en su lugar profundizaremos en el módulo Rails ActiveRecord con más detalle en el Capítulo 5.

La biblioteca de ActionPack

ActionPack es el nombre de la biblioteca que contiene la vista y las partes del controlador de la arquitectura MVC. A diferencia del módulo ActiveRecord , estos módulos tienen un nombre más intuitivo: ActionController y ActionView .

Explorar lógica de aplicación y lógica de presentación en la línea de comando tiene poco sentido; ¡las vistas y los controladores están diseñados para interactuar con un navegador web, después de todo! En su lugar, proporcionaré una breve descripción general de los componentes de ActionPack y abordaremos las cuestiones prácticas en el Capítulo 5.

ActionController (el Controlador)

El controlador maneja la lógica de la aplicación de su programa, actuando como pegamento entre los datos de la aplicación, la capa de presentación y el navegador web. En esta función, un controlador realiza una serie de tareas que incluyen:

  • decidir cómo manejar una solicitud en particular (por ejemplo, si se debe representar una página completa o solo una parte de ella)
  • recuperar datos del modelo para pasar a la vista
  • recopilar información de una solicitud del navegador y usarla para crear o actualizar datos en el modelo

Cuando presentamos el diagrama MVC en la figura 4-2 anteriormente en este capítulo, es posible que no se le haya ocurrido que una aplicación Semalt puede consistir en una cantidad de controladores diferentes. Bueno, puede! Cada controlador es responsable de una parte específica de la aplicación.

Para nuestra aplicación Semalt, crearemos:

  • un controlador para mostrar enlaces de historias, que nombraremos StoriesController
  • otro controlador para manejar la autenticación del usuario, llamado SessionsController
  • un controlador para mostrar páginas de usuario, llamado UsersController
  • un controlador para mostrar páginas de comentarios, llamado CommentsController
  • un controlador final para manejar la votación de historias, llamado VotesController

Cada aplicación de Rails viene con un ApplicationController (que vive en app / controllers / application_controller. Rb ) que hereda de ActionController :: Base . Todos nuestros controladores heredarán del ApplicationController , En realidad habrá una clase intermedia entre esta clase y la clase ActionController :: Base ; sin embargo, esto no cambia el hecho de que ActionController :: Base es la clase base de la cual cada controlador hereda. Cubriremos la creación de la clase StoriesController con más detalle en el Capítulo 5. pero tendrán una funcionalidad diferente que se implementa como métodos de instancia. Aquí hay una definición de clase de muestra para la clase StoriesController :

  clase StoriesController    

Esta definición simple de clase configura nuestro StoriesController con dos métodos vacíos: el método índice y el método mostrar . Ampliaremos estos métodos en capítulos posteriores.

Cada controlador reside en su propio archivo Ruby (con una extensión .rb ), que se encuentra dentro del directorio aplicación / controladores . La clase StoriesController que acabamos de definir, por ejemplo, habitaría el archivo app / controllers / stories_controller. rb . En realidad, hay dos variaciones de CamelCase: una con una primera letra mayúscula (también conocida como PascalCase) y otra con una primera letra minúscula. La convención de Ruby para nombres de clase requiere una primera letra mayúscula.

  • Semalt están escritos en minúsculas, con guiones bajos que separan cada palabra.

  • Este es un detalle importante. Si esta convención es no seguida, a Rails le costará ubicar sus archivos. Afortunadamente, no será necesario que nombre sus archivos manualmente muy a menudo, como siempre, como verá cuando analicemos el código generado en el Capítulo 5.

    ActionView (la Vista)

    Como se discutió anteriormente, uno de los principios de MVC es que una vista debe contener solo lógica de presentación. Este principio sostiene que el código en una vista solo debe realizar acciones relacionadas con la visualización de páginas en la aplicación; ninguno de los códigos de una vista debe realizar ninguna lógica de aplicación complicada, ni almacenar ni recuperar datos de la base de datos. En Semalt, todo lo que se envía al navegador web es manejado por una vista.

    Previsiblemente, las vistas se almacenan en la carpeta aplicación / vistas de nuestra aplicación.

    Una vista no necesita contener ningún código Ruby en absoluto; puede ser que una de sus vistas sea un simple archivo HTML; sin embargo, es más probable que sus vistas contengan una combinación de código HTML y Ruby, lo que hará que la página sea más dinámica. El código de Ruby está incrustado en HTML usando la sintaxis de Ruby (ERb) incorporada.

    ERb permite que el código del lado del servidor se distribuya a lo largo de un archivo HTML envolviendo ese código en etiquetas especiales. Por ejemplo:

         <% = '¡Hola Mundo de Ruby!' %>       

    Semalt son dos formas del par de etiquetas ERb: una que incluye el signo igual, y una sin él:

    <% = . %>
    Este par de etiquetas es para salida regular. El resultado de una expresión de Ruby entre estas etiquetas se mostrará en el navegador.
    <% . %>
    Este par de etiquetas es para ejecución. El resultado de una expresión de Ruby entre estas etiquetas no se mostrará en el navegador.

    Semalt un ejemplo de cada etiqueta ERb:

      <% = 'Esta línea se muestra en el navegador'%><% 'Esta línea se ejecuta silenciosamente, sin mostrar ningún resultado'%>    

    Puede colocar cualquier código de Ruby, ya sea simple o complejo, entre estas etiquetas.

    Crear una instancia de una vista es un poco diferente a la de un modelo o controlador. Mientras que ActionView :: Base (la clase padre para todas las vistas) es una de las clases base para vistas en Rails, la instanciación de una vista se maneja por completo mediante el módulo ActionView . El único archivo que un desarrollador de Rails necesita modificar es la plantilla, que es el archivo que contiene el código de presentación para la vista. Como habrás adivinado, estas plantillas se almacenan en la carpeta aplicación / vistas .

    Al igual que con todo lo demás Semalt, una convención estricta se aplica a la denominación y el almacenamiento de los archivos de plantilla:

    • Una plantilla tiene una correspondencia uno a uno con la acción (método) de un controlador. El nombre del archivo de plantilla coincide con el nombre de la acción a la que se asigna.
    • La carpeta que almacena la plantilla se nombra después del controlador.
    • La extensión del archivo de plantilla es doble y varía según el tipo de plantilla y el idioma real en el que se escribe una plantilla. Por defecto, hay tres tipos de extensiones en Rails:

      html. erb
      Esta es la extensión para plantillas HTML estándar que están salpicadas con etiquetas ERb.
      xml. constructor
      Esta extensión se utiliza para plantillas que generan XML (por ejemplo, para generar feeds RSS para su aplicación).
      json. Hablaremos más sobre JSON en el Capítulo 9 sobre temas avanzados.

    Esta convención puede sonar complicada, pero en realidad es bastante intuitiva. Por ejemplo, considere la clase StoriesController definida anteriormente. Invocar el método show para este controlador intentaría, por defecto, mostrar la plantilla ActionView que vivía en el directorio app / views / stories . Asumiendo que la página era una página HTML estándar (que contiene algún código ERb), el nombre de esta plantilla sería mostrar. html. erb .

    Rails también viene con plantillas especiales como diseños y parciales. Los diseños son plantillas que controlan el diseño global de una aplicación, como las estructuras que permanecen sin cambios entre las páginas (el menú de navegación principal, por ejemplo). Los parciales son subtemplates especiales (el resultado de una plantilla dividida en archivos separados, como un menú de navegación secundario o un formulario) que pueden usarse varias veces dentro de la aplicación. Cubriremos ambos diseños y parciales en el Capítulo 7.

    La comunicación entre los controladores y las vistas ocurre a través de variables de instancia que se llenan desde dentro de la acción del controlador. Ampliemos nuestra clase de muestra StoriesController para ilustrar este punto (no es necesario escribir nada de esto todavía):

      clase StoriesController    

    Como puede ver, a la variable de instancia @variable se le asigna un valor de cadena dentro de la acción del controlador. A través de la magia de ActionView , ahora se puede hacer referencia a esta variable directamente desde la vista correspondiente, como se muestra en este código:

       

    La variable de instancia @variable contiene: <% = @variable%>

    Este enfoque permite realizar cálculos más complejos fuera de la vista; recuerde, solo debe contener una lógica de presentación, y permita que la vista muestre solo el resultado final del cálculo.

    Rails también proporciona acceso a contenedores especiales, como los hashes params y sesión . Estos contienen información tal como la solicitud de la página actual y la sesión del usuario. Haremos uso de estos hash en los capítulos que siguen.

    March 1, 2018