2010-03-02 7 views
7

Je construis cette application reposante en utilisant RoR, et je trouve qu'il est un peu difficile de tracer une ligne entre les choses qui devraient aller sur le modèle, et les choses qui devraient aller sur le contrôleur . A titre d'exemple, j'ai 7 méthodes sur mon contrôleur (celles qui le rendent reposant ie index(), show(), create(), update() ...), et trouvent souvent qu'il est nécessaire de ajoutez des méthodes supplémentaires, et faites-le en les créant en tant que membres.Tracer la ligne entre le modèle et le contrôleur

Ce que je voudrais accomplir ici, est de recueillir l'expérience de vous les gars sur ce qui se passe où (c.-à-dois-je tenir toutes les interactions de base de données sur le modèle, et il suffit d'appeler ces méthodes à partir du contrôleur?)

Aussi, en ajoutant des choses qui n'impliquent pas DB à mon contrôleur, c'est-à-dire que je veux faire un appel HTTP à l'écran - gratter certaines données d'un site Web.

Les appels HTTP peuvent devenir gros et salissants. Est-ce que tout ceci devrait aller à mon contrôleur, ou devrait-il aller dans une classe ou un module séparé, et être seulement inclus dans mon contrôleur pour qu'il puisse être appelé?

Si oui, quelle serait la meilleure approche pour le faire? Je suis un peu confus avec tout cela, alors ce serait bien d'avoir quelqu'un d'autre.

Merci à l'avance

+0

J'ai trouvé que j'ai rarement besoin d'actions supplémentaires dans un contrôleur reposant. Au lieu de cela, je déplace cette action vers son propre contrôleur où il peut s'agir d'une action standard avec un nom approprié. Cependant, il a certainement fallu du temps pour changer d'état d'esprit. – wesgarrison

+0

@wesgarrison: pourriez-vous donner un exemple d'utilisation des actions REST avec un contrôleur différent? – giorgian

+0

@giorgian: Désolé pour la réponse tardive. Si j'ai un helpdesk avec des tickets, je pourrais vouloir ajouter une méthode dans tickets_controller appelée my_tickets (pour lister mes tickets). Au lieu de cela, je pense à cela comme une ressource distincte: les billets qui m'appartiennent; ce qui en fait un nouveau contrôleur: my_tickets_controller avec seulement une action index() (je ne montre pas/met à jour dans my_tickets, ceux-ci vont à tickets_controller). De cette façon, le contrôleur contrôle les informations sélectionnées et présentées à la vue. Exemple trivial, mais j'espère qu'il illustre le concept. Pensez aux ressources avec index/show/create/update. – wesgarrison

Répondre

3

Il fait partie de Domain Driven Design.

Le domaine est la sphère de connaissances qui définit la zone avec laquelle l'application tente de travailler et de résoudre des problèmes.

La couche Modèle est considérée comme la couche de domaine. C'est ici que sont conservées toutes les règles qui définissent le domaine ou la logique métier. Le modèle agit comme un filtre entre les données réelles et le reste de l'application d'une manière qui définit le domaine. Les détails d'implémentation du domaine (mySQL ou MSSql ou Webservice ou fichier XML ou page Web externe ou autre) sont masqués par le modèle.

Le contrôleur est juste le messager. Son travail consiste à prendre des messages de l'utilisateur et à les transmettre au modèle. Le Modèle reçoit une réponse et le Contrôleur élabore la meilleure façon de transmettre ceci à l'utilisateur. La vue est comme le maquilleur, s'assurant juste que les données semblent bonnes et présentables pour l'utilisateur.

Le site Web que vous gravez peut être considéré comme faisant partie du domaine. Ce site contient des connaissances qui définissent le monde défini par votre application. Le processus de scannage consiste à sculpter ces connaissances de manière à ce qu'elles correspondent à la vue du reste du monde définie par votre application. Le contrôleur ne se soucie pas d'où cette connaissance vient, il passera juste le message sur la vue. Le View va embêter les données et les rendre jolies et les envoyer à l'utilisateur, qui est complètement inconscient de tout le processus et voit juste une jolie page web!

+0

Belle explication. Merci beaucoup! –

0

Quand je l'ai utilisé les appels SOAP de Rails, qui est similaire à ce que vous parlez d'une façon, je traitais ceux comme source de données, donc à mon avis, ils appartenaient à le modèle. Vous pouvez aussi choisir, si la fonctionnalité est quelque peu générique, d'écrire un plugin pour faire ce travail, ou pour trouver un plugin qui fait déjà ce que vous voulez déjà et l'utilise.

En cas de doute, pensez à votre modèle en tant qu'application et à votre vue/contrôleur en tant qu'interface. Si ce n'est pas clairement l'interface appartient probablement dans le modèle.

This question may help.

1

Les choses racleuse devrait aller dans un modèle non ActiveRecord, et le contrôleur doit simplement appeler des méthodes de ce modèle.

Il existe un modèle example symétrique d'un modèle AR sans tableau et one d'un modèle non AR sur railscasts.

Ainsi, votre contrôleur ferait quelque chose comme:

def index 
    @some_things = SomeThing.all 
end 

def show 
    @some_thing = SomeThing.find params[......] 
end 

Et votre modèle SomeThing mettrait en œuvre la logique nécessaire.

+1

D'accord; Rails a généralement un ratio 1: 1: Model, mais c'est seulement parce que la base de données est le plus souvent la source de données. Les modèles sont d'abord destinés à la logique métier, puis à la seconde. – meagar

+0

Donc, diriez-vous que mes trucs de mise au rebut devraient être sur un modèle séparé, et je voudrais juste étendre la classe sur mon contrôleur? –

+0

La préoccupation du contrôleur est de rassembler les paramètres (le cas échéant) à transmettre au modèle; le modèle ne devrait rien savoir des utilisateurs, des requêtes, des querystrings, etc. – giorgian

3

D'une manière générale, une bonne approche (pas de flamme de la religion, plz) est d'avoir minces contrôleurs et graisse modèles. De cette façon, vous pouvez également tester facilement "les choses" que les modèles sont censés faire ...

+0

Fat models, contrôleurs maigres: http://weblog.jamisbuck.org/2006/10/18/skinny-controller-fat-model – wesgarrison

1

Je m'en tiens aux règles du contrôleur fin et des modèles gros. Compte tenu d'une approche reposante, je conserve tous les contrôleurs à cette norme et ne pas avoir d'autres méthodes en dehors de la norme par défaut. Si j'ai besoin de nouvelles fonctionnalités et notez les méthodes font des choses similaires (ou auraient un nom similaire e.g group_add, group_remove) Je crée un nouveau contrôleur et utilise des modèles existants et crée de nouvelles méthodes dans le modèle. Cela permet également une approche reposante de ces actions supplémentaires de manière significative et, spécifiquement, chaque action a une spécification étroitement définie pour son fonctionnement, il ne fera jamais plus d'une chose. Rien de pire que d'utiliser un appel API qui fait deux choses dépend de comment il est appelé.

Une approche que j'utilise est de traiter la requête aussi rapidement que possible en utilisant le moins de code possible et en faisant abstraction des tâches/opérations complexes dans le modèle.

Questions connexes