Concernant ton gist une recommandation, évite de faire des classes qui héritent
de Struct.new.
Ça crée déjà une classe donc tu ajoutes une niveau inutile.
Tu peux faire ceci à la place:
MaClasse = Struct.new(:a, :b) do
def plop
"toto"
end
end
Pour le reste question de point de vue, je trouve qu'on a plus de fierté à
faire notre travail du mieux qu'on peut ;)
Simon Courtois
On Monday 3 June 2013 at 21:29, Guirec Corbel wrote:
> J'ai fait un gist avec ma solution : https://gist.github.com/GCorbel/5699834.
> Je penses que je suis content avec ça.
>
> Tout de même, c'est pas facile de vouloir faire son métier comme il faut. Ha
> que j'étais bien quand je faisais du PHP pourri qui bugait tout le temps et
> qui n'avait aucune architecture mais que je m'en foutais. C'est une grosse
> prise de tête de vouloir toujours faire au mieux. Je ne suis jamais sûre
> d'avoir fait du bon code...
>
>
> Le 3 juin 2013 13:07, Simon Courtois <[email protected]
> (mailto:[email protected])> a écrit :
> > C'est un edge case et selon moi dans le cas du remplacement de DCI par
> > SimpleDelegator il ne s'applique pas plus que ça.
> > Cela dit, si on est est dans une situation de "contexte" ça me choquerait
> > pas que InfravisionPotionModule implémente un "observe" décoré.
> > Au final c'est ce que je fais dans Draper quand j'en ai besoin.
> >
> > Pour le reste, je pense que tu as raison de rester sur des Service objects,
> > c'est une bonne façon de fonctionner.
> >
> > Bonne journée,
> >
> >
> >
> > Simon Courtois
> >
> >
> > On Monday 3 June 2013 at 18:59, Guirec Corbel wrote:
> >
> > > Simon, As-tu vu ça :
> > > http://devblog.avdi.org/2012/01/31/decoration-is-best-except-when-it-isnt/?
> > > Il peut y avoir quelques soucis à utiliser SimpleDelegator.
> > >
> > > Je pense que je vais continuer à faire comme je fais. Mettre de la
> > > logique dans le contrôleur et utiliser des services objects quand il y a
> > > un logique un peu plus complexe. À chaque fois qu'il y a besoin de
> > > callbacks il est mieux de le remplacer par un service object. Si jamais
> > > j'ai besoin d'utiliser un héritage je ferais un rôle à la place.
> > >
> > > Un exemple de code que j'aime bien :
> > >
> > > class MessagesController < InheritedResource::Base
> > > def create
> > > sender = User.find(params[:send_id])
> > > receiver = User.find(params[:receiver_id])
> > >
> > > notifier = MessageNotifier.new(sender, receiver)
> > > notifier.call
> > >
> > > MessageGeocoder.new(notifier.message).call
> > >
> > > create!
> > > end
> > > end
> > >
> > > class MessageNotifier < Struct.new(:sender, :receiver, :message)
> > > def self.call(sender, receiver)
> > > MessageNotifier.new(sender, receiver).call
> > > end
> > >
> > > def call
> > > receiver.extend(CollectorRole)
> > > #traitement
> > > end
> > > end
> > >
> > > class MessageGeocoder < Struct.new(:message)
> > > def self.call(message)
> > > MessageGeocoder.new(message).call end
> > >
> > > def call
> > > #traitement
> > > end
> > > end
> > >
> > > module CollectorRole
> > > def paintings
> > > #find paintings
> > > end
> > > end
> > >
> > > Je crois que c'est propre. Ça serait facile de factoriser la méthode
> > > "self.call". La différence entre un service object et un context c'est
> > > que j'ai l'impression que le context doit prendre tout le traitement
> > > faire dans l'action d'un contrôleur. Un service object fait quelque chose
> > > de plus petit et on peut en utiliser plusieurs par action.
> > >
> > > Ça reste facile à comprendre et a tester. Je ne me sens pas tyranniser
> > > par le DCI. Avec le DCI ça m'aurait gêner d' utiliser "@user = User.all"
> > > dans un contrôleur. Avec un service object je fais ce que je veux.
> > >
> > > Vous en pensez quoi?
> > >
> > >
> > > Le 3 juin 2013 12:00, Olivier El Mekki <[email protected]
> > > (mailto:[email protected])> a écrit :
> > > > 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 (http://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]
> > > > > (mailto:[email protected])
> > > > > Pour résilier votre abonnement envoyez un e-mail à l'adresse
> > > > > [email protected]
> > > > > (mailto:[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]
> > > > > (mailto:railsfrance%[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]
> > > > (mailto:[email protected])
> > > > Pour résilier votre abonnement envoyez un e-mail à l'adresse
> > > > [email protected]
> > > > (mailto:[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]
> > > > (mailto:railsfrance%[email protected]).
> > > > Pour plus d'options, visitez le site
> > > > https://groups.google.com/groups/opt_out .
> > > >
> > > >
> > >
> > > --
> > > --
> > > 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] (mailto:[email protected])
> > > Pour résilier votre abonnement envoyez un e-mail à l'adresse
> > > [email protected]
> > > (mailto:[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]
> > > (mailto:[email protected]).
> > > Pour plus d'options, visitez le site
> > > https://groups.google.com/groups/opt_out .
> > >
> > >
> >
> > --
> > --
> > 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] (mailto:[email protected])
> > Pour résilier votre abonnement envoyez un e-mail à l'adresse
> > [email protected]
> > (mailto:[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]
> > (mailto:railsfrance%[email protected]).
> > Pour plus d'options, visitez le site
> > https://groups.google.com/groups/opt_out .
> >
> >
>
> --
> --
> 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] (mailto:[email protected])
> Pour résilier votre abonnement envoyez un e-mail à l'adresse
> [email protected]
> (mailto:[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]
> (mailto:[email protected]).
> Pour plus d'options, visitez le site https://groups.google.com/groups/opt_out
> .
>
>
--
--
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 .