web-dev-qa-db-fra.com

des lignes directrices pour savoir où placer les classes dans Rails applications qui ne conviennent pas n'importe où

Je me demande s'il existe des meilleures pratiques pour savoir où placer les fichiers non standard Ruby dans Rails apps, celles qui ne correspondent à aucune des les répertoires par défaut (controllers/models etc.).

Je parle des classes qui sont utilisées par les contrôleurs/modèles, etc., mais qui ne sont des sous-classes d'aucune des classes de base Rails. Classes qui incluent des fonctionnalités extraites des modèles pour les rendre moins grasses. Certains d'entre eux ressemblent à des modèles mais ne sont pas des modèles AR, certains ressemblent davantage à des "services", certains sont quelque chose entre les deux ou autre chose.

Quelques exemples aléatoires:

  • Classes de "stratégie" qui gèrent l'authentification avec mot de passe, via facebook etc.
  • Objets "XParams" qui encapsulent des paramètres ou objets "XCreator" qui gèrent le traitement des paramètres pour exécuter une action complexe qui aboutit à la création de certains modèles AR à la fin
  • classes qui effectuent des requêtes vers des API externes ou encapsulent ces requêtes et réponses
  • de faux modèles qui peuvent être substitués à un vrai modèle AR (par exemple, un utilisateur invité)
  • Resque jobs
  • des classes qui stockent et lisent les informations de Redis
  • des classes qui exécutent des actions spécifiques telles que le traitement de données, la génération de rapports, etc. et sont appelées à partir de tâches Resque ou de tâches de rake

J'en ai beaucoup maintenant, certains d'entre eux sont ajoutés à lib qui finit comme une pile de classes et de modules aléatoires, certains se faufilent dans app/models. J'aimerais organiser cela d'une manière ou d'une autre, mais je ne sais pas par où commencer.

Seuls les modèles AR devraient entrer dans app/models? Ou est-il correct de mettre également des modèles de domaine ou d'assistance? Comment décidez-vous si quelque chose est un modèle?

Tout ce qui ne rentre pas dans app doit-il aller dans lib? Ou peut-être devrais-je ajouter quelques nouveaux sous-répertoires personnalisés à app? Quels sous-répertoires et comment diviser les classes personnalisées?

Comment gérez-vous cela dans vos projets? Je sais que chaque projet est un peu différent, mais il doit y avoir des similitudes.

42
Kuba Suder

Bonne question - je n'ai pas de réponse concrète pour vous

mais je recommande de consulter ce post - http://blog.codeclimate.com/blog/2012/02/07/what-code-goes-in-the-lib-directory/ - assurez-vous lire tous les commentaires

sur un projet en cours j'ai une tonne d'objets non-ActiveRecord sous app/models, ça marche mais pas idéal je mets du code spécifique non applicatif 'réutilisable' sous lib

d'autres alternatives que j'ai essayées sur des projets secondaires (disons que nous avons un tas d'objets de commande) Rails est une douleur quand il s'agit d'espaces de noms sous l'application, il charge tout dans le même espace de noms par défaut

app/
  commands/
    products/create_command.rb         # Products::CreateCommand
    products/update_price_command.rb   # Products::UpdatePriceCommand

alternatif, tout sauf Rails sous src ou un répertoire app_name

app/
  src/
    commands/
      create_product.rb         # Commands::CreateProduct
      update_product_price.rb   # Commands::UpdateProductPrice

Je n'ai pas trouvé de bonne solution pour cela, idéalement le 2ème est meilleur, mais ce serait bien de ne pas avoir le répertoire supplémentaire sous app, de cette façon vous ouvrez l'application et voyez les contrôleurs, commandes, modèles etc ...

15
house9

Vous touchez à un certain nombre de cas d'utilisation différents, et je pense que cette partie est la plus proche de la "bonne" réponse:

J'en ai beaucoup maintenant, certains d'entre eux sont ajoutés à lib qui se termine par une pile de classes et de modules aléatoires, certains se glissent dans des applications/modèles. J'aimerais organiser cela d'une manière ou d'une autre, mais je ne sais pas par où commencer.

C'est à peu près juste dans mon livre. La seule chose que vous ne mentionnez pas est l'extraction de divers morceaux dans des gemmes distinctes. Les classes qui parlent à des services externes sont d'excellents candidats à l'extraction, tout comme les classes de stratégie si elles sont suffisamment générales. Ceux-ci peuvent être privés, car l'exécution de votre propre serveur de gemmes n'est pas difficile, et vous pouvez évidemment les réutiliser dans les applications ROR.

Enfin et plus concrètement, resquez les jobs que je fourre dans lib/jobs.

Ma règle de base est que si c'est un modèle d'une sorte, il va dans app/models. Sinon, il appartient probablement à lib ou à un sous-répertoire correctement nommé de celui-ci, par ex. lib/jobs, lib/extensions, lib/external, ou semblable.

9
Dave S.

Si vous êtes intéressé, j'ai également écrit un article de suivi à ce sujet un peu plus tard pour résumer ce que j'ai trouvé: http://blog.lunarlogic.io/2013/declutter-lib-directory/

3
Kuba Suder

Je place toutes les classes de modèle (comme les sous-classes STI) dans apps/models. Je place mes autres classes dans lib, car il semble que ce soit le meilleur endroit pour les mettre. Il m'est facile de savoir où chercher. Il est également plus facile pour moi de regrouper mes tests car mes classes de modèles sont toutes au même endroit.

En ce qui concerne les conventions, je répugne à mettre des classes auxiliaires dans app/models. S'ils sont des classes de présentateurs, ils appartiennent au app/helpers. S'ils ne le sont pas, lib semble être le meilleur endroit pour eux.

3
Richard Brown

Souvent, mes classes se retrouvent dans lib dans des sous-répertoires où les modules portant le même nom que le sous-répertoire sont chargés de les inclure. (Rails est très délicat sur les noms de fichiers et les noms de classe en ce qui concerne l'autochargeur.)

Une autre option consiste à encapsuler chaque module dans sa propre gemme, puis à la référencer via votre Gemfile. Cela permet le partage de code entre les projets.

1
cfeduke