Hello, Personnellement, dans le DCI, l'idée d'avoir des méthodes disponibles sur le model uniquement lorsqu'on en a besoin m'intéresse peu : ça m'intéresse que mon code soit lisible, donc je vais utiliser des modules ou des concerns, mais peu m'importe que des méthodes soient disponibles sur mon instance alors qu'elle n'en a pas besoin.
Le concept de context m'a en revanche beaucoup plus séduit, notamment parce qu'il me permet de sortir de l'enfer du STI et permet de résoudre des problèmes que le STI lui-même ne permet pas de résoudre. J'utilise aujourd'hui quotidiennement des contextes via cette implémentation : https://gist.github.com/oelmekki/474dcc99649a82986dc3 L'idée est de faire gérer les validations, filtrages de paramètres et before / after save (qui seraient conditionnels) par une classe dédiée. Ça permet d'éviter d'avoir deux models (ou plus) pour gérer des validations spécifiques de ce qui est finalement une seule resource. Ça permet également de prendre en compte ce principe de rôle (sans toutefois nécessiter que le rôle soit définit dans une classe, dans mon implémentation). Parce qu'après tout, lorsqu'un admin edit un utilisateur, ce n'est pas la même chose que lorsqu'un utilisateur s'edite lui même (pas les mêmes validations, pas les mêmes callbacks, pas les mêmes attributs autorisés, etc). La documentation inclue dans ce fichier en dit plus long. Et effectivement, pas question de forcer son usage dans toutes les actions : on doit pouvoir faire un `Foo.all` si c'est tout ce qui est nécessaire :) Note : pour exécuter ce code, il faut utiliser active_record, strong_parameters et cette lib : https://gist.github.com/oelmekki/4a82dce1d9c2a5d66936 On 10:40 Mon 03 Jun , Guirec Corbel wrote: > Bonjour à tous, > > J'ai lu quelques trucs à propos du DCI (Data Context Integration) et je ne > sais pas quoi en penser. J'aimerais avoir votre avis sur la question. > > Pour ceux qui ne connaissent pas, je vous conseil de lire ceci : > http://mikepackdev.com/blog_posts/24-the-right-way-to-code-dci-in-ruby. > > J'aime bien le concept de rôle. Dans l'application que je fais j'ai des > utilisateurs et un type d’utilisateur spécial, le collectionneur. Si j'ai > bien compris le concept il faut écrire un role comme ceci : > > module CollectorRole > def paintings > Painting.where(user_id: self.id) > end > end > > Et pour avoir toutes les peintures d'un collectionneur je pourrais faire > ceci : > > user = User.new > user.extend CollectorRole > user.paintings > > Je n'aurais donc que deux modèles minimaux, User et Painting, représentant > uniquement les données (présente dans la base donnée). Si je veux ajouter > un comportement à mon utilisateur je l'ajouterai dans un rôle. Je respect > donc plus facilement le SRP (Single Responsability Principle). Ça remplace > un héritage. > > Là ou j'ai du mal c'est au niveau du context et du contrôleur. Un exemple > qui fonctionne pas trop mal serait dans le cas ou je voudrais faire une > fonctionnalité qui permet aux utilisateurs de contacter les > collectionneurs. Je ferais un truc du genre : > > class UserContactCollectorContext > attr_reader :user_from, user_to > > def self.call(user_from, user_to) > UserContactCollectorContext.new(user_from, user_to).call > end > > def initialize(user_from, user_to) > @user_from, @user_to = user_from, user_to > @user_to.extend CollectorRole > end > > def call > @paintings = @user_to.paintings > # traitement et envoi du mail > end > end > > Et dans mon contrôleur j'aurais ceci : > > class MessagesController < ApplicationController > def send_message_to_collector > UserContactCollectorContext.call(User.find(params[:user_from]), > User.find(params[:user_to])) > end > end > > Ce code me convient. Là ou ça ne me convient pas c'est quand je veux tout > simplement la liste des utilisateurs. Il faudrait faire un contrôleur du > genre : > > class UsersController < ApplicationController > def index > @users = UserAllContext.call > end > end > > Il y a un exemple similaire ici : > https://github.com/randx/rails-dci-example/blob/master/app/controllers/documents_controller.rb > > Franchement, créé un context pour chaque action de ce type je trouve que > c'est trop. C'est plus simple de faire "@users = User.all". L'avantage > c'est que ça sépare vraiment la logique. Le contrôleur n'a pas à savoir ce > que fait le context. S'il y a un mail envoyé, un géocodage ou tout le > reste, le contrôleur ne le sait pas. C'est vraie pour l'inverse. Le context > ne sait pas ce que fait le contrôleur. On a donc un séparation franche > entre la logique métier et la partie système. > > J'ai lu le livre CleanRuby. Je penses que Jim Gay va trop loin. Il créé un > context "framework agnostic" qui appel des fonctions du contrôleur. J'ai du > mal à comprendre pourquoi il écrit un livre prônant la valeur du "Skinny > Controller" alors qu'il a du code comme ceci : > https://github.com/radiant/radiant/blob/master/app/models/page.rb. > > Qu'en pensez-vous? Est-ce que quelqu'un d'entre vous à mis en pratique ce > concept? Quels sont vos impressions? > > Merci à tous! > > -- > -- > Vous avez reçu ce message, car vous êtes abonné au groupe "Railsfrance" de > Google Groups. > Pour transmettre des messages à ce groupe, envoyez un e-mail à l'adresse > [email protected] > Pour résilier votre abonnement envoyez un e-mail à l'adresse > [email protected] > --- > Vous recevez ce message, car vous êtes abonné au groupe Google Groupes > Railsfrance. > Pour vous désabonner de ce groupe et ne plus recevoir d'e-mails le > concernant, envoyez un e-mail à l'adresse > [email protected]. > Pour plus d'options, visitez le site https://groups.google.com/groups/opt_out > . > > -- Olivier El Mekki. -- -- Vous avez reçu ce message, car vous êtes abonné au groupe "Railsfrance" de Google Groups. Pour transmettre des messages à ce groupe, envoyez un e-mail à l'adresse [email protected] Pour résilier votre abonnement envoyez un e-mail à l'adresse [email protected] --- Vous recevez ce message, car vous êtes abonné au groupe Google Groupes Railsfrance. Pour vous désabonner de ce groupe et ne plus recevoir d'e-mails le concernant, envoyez un e-mail à l'adresse [email protected]. Pour plus d'options, visitez le site https://groups.google.com/groups/opt_out .
