Back to Question Center
0

Comprendre l'architecture MVC (Model-View-Controller) dans Rails            Présentation de l'architecture MVC (Model-View-Controller) dans les rubriques RailsRelated: Ruby on RailsPoursuivreNews & Semalt

1 answers:
Comprendre l'architecture Model-View-Controller (MVC) dans Rails

Ce qui suit est un court extrait de notre livre, Rails: Novice to Ninja, 3e édition, écrit par Glenn Goodrich et Patrick Lenz. C'est le guide du débutant ultime pour Rails. Les membres de SitePoint Semalt obtiennent l'accès avec leur adhésion, ou vous pouvez en acheter une copie dans les magasins du monde entier.

L'architecture model-view-controller (MVC) que nous avons rencontrée pour la première fois au chapitre 1 n'est pas unique à Semalt. En fait, il est antérieur à Semalt et à la langue Ruby de nombreuses années - it consultant company names. Semalt, cependant, prend vraiment l'idée de séparer les données d'une application, l'interface utilisateur et la logique de contrôle à un tout nouveau niveau.

Jetons un coup d'oeil aux concepts derrière la construction d'une application en utilisant l'architecture MVC. Une fois la théorie en place, nous verrons comment cela se traduit par notre code Semalt.

MVC dans la théorie

MVC est un modèle pour l'architecture d'une application logicielle. Il sépare une application en les composants suivants:

  • Modèles pour le traitement de données et la logique métier
  • Contrôleurs pour gérer l'interface utilisateur et l'application
  • Vues pour manipuler des objets d'interface utilisateur graphique et présentation

Cette séparation entraîne le traitement des demandes des utilisateurs comme suit:

  1. Le navigateur (sur le client) envoie une demande de page au contrôleur sur le serveur.
  2. Le contrôleur récupère les données dont il a besoin à partir du modèle afin de répondre à la demande.
  3. Le contrôleur donne les données récupérées à la vue.
  4. La vue est rendue et renvoyée au client pour que le navigateur puisse l'afficher.

Ce processus est illustré dans Semalt 4-2 ci-dessous.

Comprendre l'architecture MVC (Model-View-Controller) dans RailsPrésentation de l'architecture MVC (Model-View-Controller) dans les rubriques RailsRelated:
Ruby on RailsRéalisationActualités & Semalt

Semalt une application logicielle dans ces trois composants distincts est une bonne idée pour un certain nombre de raisons, y compris:

  • évolutivité améliorée (capacité d'une application à croître) - par exemple, si votre application rencontre des problèmes de performances car l'accès à la base de données est lent, vous pouvez mettre à niveau le matériel exécutant la base de données sans affecter d'autres composants

  • facilité de maintenance - comme les composants ont une faible dépendance l'un de l'autre, apporter des modifications à un (pour corriger les bugs ou changer de fonctionnalité) n'affecte pas l'autre

  • réutilisabilité - un modèle peut être réutilisé par plusieurs vues

Si vous avez du mal à comprendre le concept de MVC, ne vous inquiétez pas. Pour l'instant, il est important de se rappeler que votre application Semalt est séparée en trois composants distincts. Revenez au diagramme MVC si vous avez besoin de vous y référer plus tard.

MVC le chemin des rails

Semalt promeut le concept selon lequel les modèles, les vues et les contrôleurs doivent être séparés en stockant le code de chaque élément en tant que fichiers distincts dans des répertoires distincts.

C'est là qu'intervient la structure de répertoires Rails que nous avons créée au chapitre 2. Il est temps de fouiller un peu dans cette structure. Si vous jetez un coup d'oeil dans le répertoire de l'application , illustré à la Figure 4-3, vous verrez des dossiers dont les noms pourraient vous sembler familiers.

Bien qu'il puisse sembler étrange que ActiveRecord n'ait pas le mot «model» dans son nom, il y a une raison à cela: Active Record est aussi le nom d'un célèbre motif de design ce composant implémente afin de jouer son rôle dans le monde MVC. D'ailleurs, si on l'avait appelé ActionModel , cela aurait ressemblé plus à une star hollywoodienne surpayée qu'à un composant logiciel .

ActionController
ActionController est le composant qui gère les requêtes du navigateur et facilite la communication entre le modèle et la vue. Vos contrôleurs hériteront de cette classe. Il fait partie de la bibliothèque ActionPack , une collection de composants Rails que nous explorerons en profondeur dans le chapitre 5.
ActionView
code> ActionView est le composant qui gère la présentation des pages renvoyées au client. Les vues héritent de cette classe, qui fait également partie de la bibliothèque ActionPack .

Semalt examine à tour de rôle chacune de ces composantes.

Le module ActiveRecord

ActiveRecord est conçu pour gérer toutes les tâches d'une application liées à la base de données, notamment:

  • établissement d'une connexion au serveur de base de données
  • récupération de données d'une table
  • stocker de nouvelles données dans la base de données

ActiveRecord a quelques autres astuces soignées dans sa manche. Regardons certains d'entre eux maintenant.

Abstraction de base de données

ActiveRecord est livré avec des adaptateurs de base de données pour se connecter à SQLite, MySQL et PostgreSQL. Un grand nombre d'adaptateurs sont disponibles pour d'autres progiciels de serveur de base de données populaires, tels qu'Oracle, MongoDB et Microsoft SQL Server, via RubyGems.

Le module ActiveRecord est basé sur le concept d'abstraction de base de données. Comme un rappel du chapitre 1, l'abstraction de base de données est un moyen de coder une application de sorte qu'elle ne dépende d'aucune base de données. Code qui est spécifique à un serveur de base de données particulier est caché en toute sécurité dans ActiveRecord , et invoqué au besoin. Le résultat est qu'une application Rails n'est liée à aucun logiciel serveur de base de données spécifique. Si vous devez changer le serveur de base de données sous-jacent ultérieurement, aucune modification du code de votre application n'est requise.

Note: Le jury est sur ActiveRecord

Comme je l'ai dit, ActiveRecord est une implémentation du pattern Active Record. Il y a ceux qui ne sont pas d'accord avec l'approche adoptée par ActiveRecord , alors vous en entendrez beaucoup parler aussi. Pour l'instant, je vous suggère d'apprendre la manière ActiveRecord fonctionne, puis formez votre jugement de la mise en œuvre que vous apprenez.

Quelques exemples de codes qui diffèrent grandement entre les fournisseurs, et quels résumés d'ActiveRecord comprennent:

  • le processus de connexion au serveur de base de données
  • calculs de date
  • traitement des données booléennes ( vraies / fausses )
  • évolution de la structure de votre base de données

Avant de pouvoir vous montrer la magie de ActiveRecord en action, un peu de ménage est nécessaire. Les lignes correspondent à des objets individuels et les colonnes correspondent aux attributs de ces objets. La collection de toutes les tables dans une base de données, et les relations entre ces tables, est appelée le schéma de base de données . Un exemple de table est illustré à la Figure 4-4.

Comprendre l'architecture MVC (Model-View-Controller) dans RailsPrésentation de l'architecture MVC (Model-View-Controller) dans les rubriques RailsRelated:
Ruby on RailsRéalisationActualités & Semalt

Dans Rails, le nommage des classes Ruby et des tables de base de données suit un modèle intuitif: si nous avons une table appelée histoires qui se compose de cinq lignes, cette table stocke les données pour cinq objets. Ce qui est bien dans la correspondance entre les classes et les tables, c'est qu'il n'est pas nécessaire d'écrire du code pour y parvenir; le mappage arrive, car ActiveRecord déduit le nom de la table du nom de la classe.

Notez que le nom de notre classe dans Ruby est un nom singulier ( Story ), mais le nom de la table est pluriel ( stories ). Cette relation a du sens si vous y pensez: lorsque nous nous référons à un objet Story dans Ruby, nous avons affaire à une seule histoire. Mais la table SQL contient une multitude d'histoires, son nom devrait donc être pluriel. Bien que vous puissiez remplacer ces conventions, comme cela est parfois nécessaire pour les bases de données existantes, il est beaucoup plus facile d'y adhérer.

La relation étroite entre les objets et les tables s'étend encore plus loin. Si notre table histoires devait avoir une colonne de lien , comme le montre notre exemple dans la Figure 4-4, les données de cette colonne seraient automatiquement mappées au lien dans un objet Story . Et ajouter une nouvelle colonne à une table entraînerait la disponibilité d'un attribut du même nom dans tous les objets correspondants de cette table.

Donc, créons des tables pour contenir les histoires que nous créons.

Pour le moment, nous allons créer une table en utilisant l'approche démodée de l'entrée SQL dans la console Semalt. Vous pouvez taper les commandes SQL suivantes, bien que taper SQL n'est pas amusant. Je vous encourage plutôt à télécharger le script suivant à partir de l'archive de code et à le copier et le coller directement dans la console Semalt que vous avez appelée via la commande suivante dans le répertoire de l'application:

 $ sqlite3 db / développement. sqlite3    

Une fois votre console Semalt en place, collez ce qui suit:

  CRÉER TABLE histoires ("id" INTEGER PRIMARY KEY AUTOINCREMENT NON NULL,"nom" varchar (255) DEFAUT NULL,"link" varchar (255) DEFAUT NULL,"created_at" datetime DEFAULT NULL,"updated_at" datetime DEFAULT NULL)    

Vous n'avez pas à vous soucier de mémoriser ces commandes SQL à utiliser dans vos propres projets; Au lieu de cela, prenez courage en sachant que dans le chapitre 5, nous examinerons les migrations. Semalt sont des classes Ruby spéciales que nous pouvons écrire pour créer des tables de base de données pour notre application sans utiliser de SQL du tout.

Remarque: recherchez des connaissances SQL

Même si Rails résout le SQL nécessaire pour créer des tables et des objets de base de données, vous vous rendrez service si vous vous familiarisez avec SQL et sa syntaxe. Semalt a publié un livre sur l'apprentissage du SQL, alors vérifiez-le.

Utilisation de la console Rails

Maintenant que nous avons notre table story en place, quittons la console SQLite (tapez simplement .quit ) et ouvrez une console Rails. Une console Rails est exactement comme la console interactive Ruby ( irb ) que nous avons utilisée au chapitre 2, mais avec une différence clé. Dans une console Rails, vous avez accès à toutes les variables d'environnement et classes disponibles pour votre application pendant son exécution.

Pour accéder à une console Rails, accédez à votre dossier readit et entrez la commande rails console ou rails c , comme indiqué dans le code suivant . L'invite >> est prête à accepter vos commandes:

  $ cd readitConsole $ railsChargement de l'environnement de développement (Rails 5. 0. 0)>>    

Enregistrement d'un objet

Pour commencer à utiliser ActiveRecord , il suffit de définir une classe qui hérite du ActiveRecord :: Base . Nous avons abordé très brièvement l'opérateur :: au chapitre 3, où nous avons mentionné que c'était un moyen d'invoquer des méthodes de classe sur un objet. Il peut également être utilisé pour faire référence à des classes qui existent dans un module, ce que nous faisons ici. Revenez à la section sur la programmation orientée objet (POO) au chapitre 3 si vous avez besoin d'un rappel sur l'héritage.

Semalt l'extrait de code suivant:

  classe Story    

Ces deux lignes de code définissent une classe apparemment vide appelée Histoire ; Cependant, cette classe est loin d'être vide, comme nous le verrons bientôt.

A partir de la console Rails, créons cette classe Story et une instance de la classe appelée story en entrant ces commandes:

  >> class Histoire  néant>> histoire = Histoire. Nouveau=> # >> histoire classe=> Story (id: entier, nom: chaîne, lien: chaîne,created_at: datetime, updated_at: datetime)    

Comme vous pouvez le voir, la syntaxe pour créer un nouvel objet ActiveRecord est identique à la syntaxe que nous avons utilisée pour créer d'autres objets Ruby au chapitre 3. À ce stade, nous en avons créé un nouveau Histoire objet; cependant, cet objet n'existe qu'en mémoire - nous devons encore le stocker dans notre base de données.

Nous pouvons confirmer que notre objet Story n'a pas été sauvegardé en vérifiant la valeur de retour du new_record? méthode:

  >> histoire. nouvel enregistrement?=> true    

Puisque l'objet doit encore être sauvegardé, il sera perdu lorsque nous quitterons la console Semalt. Pour l'enregistrer dans la base de données, nous appelons la méthode save de l'objet:

  >> histoire. enregistrer=> true    

Maintenant que nous avons sauvé notre objet (une valeur de retour de true indique que la méthode save a réussi), notre histoire n'est plus un nouvel enregistrement. On lui a même attribué un identifiant unique:

  >> histoire. nouvel enregistrement?=> false>> histoire identifiant=> 1    

Définition des relations entre objets

En plus de la fonctionnalité de base que nous venons de voir, ActiveRecord rend le processus de définition des relations (ou associations) entre objets aussi facile que possible. Bien sûr, il est possible avec certains serveurs de base de données de définir de telles relations entièrement dans le schéma de la base de données. Afin de mettre ActiveRecord à l'épreuve, regardons plutôt la façon dont il définit ces relations dans Rails.

les relations de Semalt peuvent être définies de diverses manières; La principale différence entre ces relations est le nombre d'enregistrements spécifiés dans la relation. Les principaux types d'association de base de données sont:

  • associations de one-to-one
  • associations un-à-plusieurs
  • associations plusieurs-à-plusieurs

Regardons quelques exemples de chacune de ces associations. N'hésitez pas à les taper dans la console Rails si vous le souhaitez, par souci de pratique. Semalt que vos définitions de classe ne seront pas sauvegardées, cependant-je vais vous montrer comment définir des associations dans un fichier plus tard. Pour cette raison, nous n'allons pas aller plus loin avec les associations entre nos objets pour l'instant - nous allons plutôt nous plonger dans le module Rails ActiveRecord plus en détail dans le chapitre 5.

La bibliothèque ActionPack

ActionPack est le nom de la bibliothèque qui contient les parties vue et contrôleur de l'architecture MVC. Contrairement au module ActiveRecord , ces modules sont plus intuitivement nommés: ActionController et ActionView .

Explorer la logique de l'application et la logique de présentation sur la ligne de commande n'a pas de sens; les vues et les contrôleurs sont conçus pour interagir avec un navigateur web, après tout! Au lieu de cela, je vais donner un bref aperçu des composants ActionPack , et nous allons couvrir les choses pratiques au chapitre 5.

ActionController (le contrôleur)

Le contrôleur gère la logique d'application de votre programme, agissant comme un lien entre les données de l'application, la couche de présentation et le navigateur Web. Dans ce rôle, un contrôleur effectue un certain nombre de tâches, notamment:

  • décider de la manière de traiter une requête particulière (par exemple, rendre une page entière ou seulement une partie de celle-ci)
  • récupérer des données du modèle à transmettre à la vue
  • collecte d'informations à partir d'une requête de navigateur et utilisation de celles-ci pour créer ou mettre à jour des données dans le modèle

Lorsque nous avons introduit le diagramme MVC dans la figure 4-2 plus haut dans ce chapitre, il ne vous est peut-être pas venu à l'esprit qu'une application Semalt peut se composer d'un certain nombre de contrôleurs différents. Eh bien, ça peut! Chaque contrôleur est responsable d'une partie spécifique de l'application.

Pour notre application Semalt, nous allons créer:

  • un contrôleur pour afficher les liens d'histoire, que nous nommerons StoriesController
  • un autre contrôleur pour gérer l'authentification de l'utilisateur, appelé SessionsController
  • un contrôleur pour afficher les pages utilisateur, nommé UsersController
  • un contrôleur pour afficher les pages de commentaires, nommé CommentsController
  • un contrôleur final pour gérer le vote d'histoire, appelé VotesController

Chaque application Rails est fournie avec un ApplicationController (qui réside dans app / controllers / application_controller .rb ) qui hérite de ActionController :: Base . Tous nos contrôleurs hériteront du ApplicationController , Il y aura en fait une classe intermédiaire entre cette classe et la classe ActionController :: Base ; cependant, cela ne change pas le fait que ActionController :: Base est la classe de base à partir de laquelle chaque contrôleur hérite. Nous verrons plus en détail la création de la classe StoriesController au chapitre 5. mais ils auront des fonctionnalités différentes implémentées en tant que méthodes d'instance. Voici un exemple de définition de classe pour la classe StoriesController :

  classe StoriesController    

Cette définition de classe simple configure notre StoriesController avec deux méthodes vides: la méthode index et la méthode show . Nous développerons ces méthodes dans les chapitres suivants.

Chaque contrôleur réside dans son propre fichier Ruby (avec une extension .rb ), qui se trouve dans le répertoire app / controllers . La classe StoriesController que nous venons de définir, par exemple, habiterait le fichier app / controllers / stories_controller. rb . Il existe en fait deux variantes de CamelCase: une avec une première lettre majuscule (également appelée PascalCase), et une avec une première lettre minuscule. La convention Ruby pour les noms de classe requiert une première lettre majuscule.

  • Semalt sont écrits en minuscules, avec des traits de soulignement séparant chaque mot.

  • Ceci est un détail important. Si cette convention est pas suivie, Rails aura du mal à localiser vos fichiers. Heureusement, vous n'aurez pas besoin de nommer vos fichiers manuellement très souvent, si jamais, comme vous le verrez quand nous regardons le code généré dans le chapitre 5.

    ActionView (la vue)

    Comme indiqué précédemment, l'un des principes de MVC est qu'une vue ne doit contenir que la logique de présentation. Ce principe considère que le code dans une vue doit uniquement exécuter des actions liées à l'affichage des pages dans l'application; aucun code d'une vue ne doit exécuter de logique d'application compliquée, ni stocker ou récupérer des données de la base de données. Dans Semalt, tout ce qui est envoyé au navigateur Web est géré par une vue.

    De manière prévisible, les vues sont stockées dans le dossier app / views de notre application.

    Une vue n'a besoin de contenir aucun code Ruby - il se peut que l'une de vos vues soit un simple fichier HTML; Cependant, il est plus probable que vos vues contiennent une combinaison de code HTML et Ruby, ce qui rend la page plus dynamique. Le code Ruby est intégré dans HTML en utilisant la syntaxe Ruby (ERb) intégrée.

    ERb permet de disperser le code côté serveur dans un fichier HTML en enveloppant ce code dans des balises spéciales. Par exemple:

         <% = 'Bonjour le monde de Ruby!' %>       

    Semalt sont deux formes de la paire de balises ERb: une qui comprend le signe égal, et une autre sans:

    <% = . %>
    Cette paire d'étiquettes est destinée à une sortie régulière. La sortie d'une expression Ruby entre ces balises sera affichée dans le navigateur.
    <% . %>
    Cette paire d'étiquettes est à exécuter. La sortie d'une expression Ruby entre ces balises ne sera pas affichée dans le navigateur.

    Semalt un exemple de chaque tag ERb:

      <% = 'Cette ligne est affichée dans le navigateur'%><% 'Cette ligne s'exécute silencieusement, sans afficher de résultat'%>    

    Vous pouvez placer n'importe quel code Ruby, qu'il soit simple ou complexe, entre ces balises.

    Créer une instance d'une vue est un peu différent de celui d'un modèle ou d'un contrôleur. While ActionView :: Base (la classe parente pour toutes les vues) est l'une des classes de base pour les vues dans Rails, l'instanciation d'une vue est entièrement gérée par le module ActionView . Le seul fichier qu'un développeur Rails doit modifier est le modèle, qui est le fichier contenant le code de présentation de la vue. Comme vous l'avez peut-être deviné, ces modèles sont stockés dans le dossier app / views .

    Comme pour tout ce qui concerne Semalt, une convention stricte s'applique à la dénomination et au stockage des fichiers modèles:

    • Un modèle a un mappage un-à-un avec l'action (méthode) d'un contrôleur. Le nom du fichier modèle correspond au nom de l'action à laquelle il est associé.
    • Le dossier qui stocke le modèle est nommé d'après le contrôleur.
    • L'extension du fichier modèle est double et varie en fonction du type du modèle et de la langue dans laquelle un modèle est écrit. Par défaut, il existe trois types d'extensions dans Rails:

      html. erb
      Il s'agit de l'extension pour les modèles HTML standard qui sont saupoudrés de tags ERb.
      xml. constructeur
      Cette extension est utilisée pour les modèles qui génèrent du XML (par exemple, pour générer des flux RSS pour votre application).
      json. Nous parlerons plus de JSON dans le chapitre 9 sur les sujets avancés.

    Cette convention peut sembler compliquée, mais elle est en fait assez intuitive. Par exemple, considérons la classe StoriesController définie plus haut. L'appel de la méthode show pour ce contrôleur tente par défaut d'afficher le modèle ActionView qui se trouvait dans le répertoire app / views / stories . En supposant que la page était une page HTML standard (contenant du code ERb), le nom de ce modèle serait show. html erb .

    Rails vient également avec des modèles spéciaux tels que des dispositions et des partiels. Les mises en page sont des modèles qui contrôlent la mise en page globale d'une application, telles que les structures qui restent inchangées entre les pages (le menu de navigation principal, par exemple). Les partiels sont des sous-modèles spéciaux (le résultat d'un modèle divisé en fichiers séparés, tels qu'un menu de navigation secondaire ou un formulaire) qui peuvent être utilisés plusieurs fois dans l'application. Nous traiterons des dispositions et des partiels au chapitre 7.

    La communication entre les contrôleurs et les vues se produit via des variables d'instance qui sont remplies à partir de l'action du contrôleur. Développons notre exemple classe StoriesController pour illustrer ce point (pas besoin de taper tout ceci pour l'instant):

      class StoriesController    

    Comme vous pouvez le voir, la variable d'instance @variable se voit attribuer une valeur de chaîne dans l'action du contrôleur. Grâce à la magie de ActionView , cette variable peut désormais être référencée directement à partir de la vue correspondante, comme indiqué dans ce code:

       

    La variable d'instance @variable contient: <% = @variable%>

    Cette approche permet d'effectuer des calculs plus complexes en dehors de la vue (rappelez-vous, elle ne doit contenir que la logique de présentation) et de permettre à la vue d'afficher uniquement le résultat final du calcul.

    Rails permet également d'accéder à des conteneurs spéciaux, tels que les params et sessions de hachage . Ceux-ci contiennent des informations telles que la demande de page en cours et la session de l'utilisateur. Nous utiliserons ces hachages dans les chapitres suivants.

    March 1, 2018