Last commit "authored a year ago". Tu vas mettre les mains dans le cambouis ptit gars :D.
2013/6/4 Guirec Corbel <[email protected]>: > Je suis tombé sur ce projet : https://github.com/cjbottaro/schizo. J'aime > bien. Ça simplifie la gestion des rôles, c'est compatible avec ActiveRecord, > ça n'inclue pas le context et c'est assez peu de code. Je pense que je > l'adopte. > > > Le 4 juin 2013 08:19, David Bourguignon <[email protected]> a écrit > : > >> Quand je vois ces exemples de DCI, je ne vois qu'une couche d'abstraction >> rajouté à un code parfaitement clair auparavant. >> >> Il faut se méfier de notre tendance en tant que développeur à >> "systèmatiser" les solutions, à "overenginerer" les solutions au nom de >> l'élégance et des principes. >> >> Je crois plus au principe du "KISS" et du "YAGNI" : ne pas écrire du code >> qui n'apporte rien pour plus tard, ou qui complique. >> Ecrire du code DCI, pourquoi pas, si on a une raison bien argumentée, pas >> juste au nom d'un principe. >> >> Extraire une méthode d'une ligne dans une classe, qui ne sera implémenté >> qu'à un endroit … je ne vois pas l'intérêt. >> >> >> >> >> Le 4 juin 2013 13:48, Guirec Corbel <[email protected]> a écrit : >> >>> Dans le fond, si je résume ce que tu dis, tu penses que dans un projet >>> c'est mieux de ne pas trop perdre de temps à se prendre la tête sur des >>> problèmes de conception alors que le client, quand il verra le projet, il >>> verra les détails comme la couleur du titre. >>> >>> Je suis d'accord avec toi. Il ne faut quand même pas oublié que >>> l'architecture est importante. Si tu néglige trop ce point tu vas le payer. >>> Je penses que, pour le moment, je vais laissé du code un peu moins beau et, >>> lors de ma prochaine release, je ferais un peu de ménage. Ceci dit, je >>> penses avoir trouvé une bonne manière de faire. J'ai une recette qui marche >>> bien. >>> >>> >>> Le 3 juin 2013 17:38, lucas di cioccio <[email protected]> a >>> écrit : >>> >>>> Hello, >>>> >>>> Le truc que je n'aime pas avec les présentations que j'ai vu sur DCI >>>> c'est pas tant l'"extend" par objet, c'est plutôt d'avoir une classe par >>>> "méthode". En fait, pour être précis, ce sont surtout les *présentations* >>>> qui ne m'ont pas plues car un peu trop dogmatiques. Les "flavors" de DCI >>>> sont peut-être une solution propre à pas mal de problèmes, mais l'important >>>> c'est d'identifier les cas où cette approche est pertinente et ce qu'elle >>>> apporte. Pour moi l'avantage de cette approche c'est de "router" vers les >>>> bonnes méthodes en fonction du contenu des données. J'estime que les >>>> modules >>>> apportent déjà l'encapsulation et donc DCI est redondant si le but n'est >>>> que >>>> l'encapsulation. >>>> Ensuite, pour "l'extend", je ne suis pas sûr que ce soit une raison >>>> suffisante pour rejeter DCI. Après tout, les perfs pourries de extend sont >>>> surtout un problème d'implémentation dans MRI, ce genre de truc peut varier >>>> d'une implémentation à l'autre. Du reste, si tes modules sont bien isolés, >>>> c'est trivial de changer du code qui fait un "extend" en une classe qui >>>> prend un objet et là où tu avais un "self" tu as l'objet en question: au >>>> final, foo.bar(machin) (DCI) ou Bar.new(foo).machin (contextes, cf. les >>>> liens d'Olivier, j'entrevoyais un problème proche ici: >>>> http://unchoke.me/blog/2012/08/15/on-states-and-behaviours/ ) c'est du >>>> kiffkiff niveau lisibilité. >>>> >>>> A mon avis, les contextes et DCI marchent bien quand il y a plusieurs >>>> prismes par lesquels regarder un objet, et que le prisme dépend d'un état >>>> contenu dans l'objet, et, qui n'est pas déterminé au "compile time" (i.e., >>>> quand tu édites ton code pour du Ruby). En gros si t'as un stream >>>> d'évènements JSON ou XML qui t'arrive dans une socket, et que tu dois >>>> tantôt >>>> les convertir des fois en pomme, parfois en prunes, et tantôt en poire ; si >>>> en plus tu as des fruits rouges et des fruits verts, ton problème se résume >>>> à trouver les bonnes méthodes dans une matrice 3x2. Si tu fais du code un >>>> peu soigné, tu ne vas pas faire une méthode spécifique à "pomme verte" >>>> (même >>>> si c'est valable dans une première itération) pour éviter que ce code path >>>> existe quand tu as une "poire". Tu ne vas pas non plus écrire une sous >>>> classe pour chaque des six combinaisons fruit/couleur (surtout que, dans >>>> cette analogie, tu pourrais avoir des éléments qui ont plusieurs couleurs). >>>> En revanche, ce serait raisonnable d'avoir 5 modules (3 qui répondent plus >>>> ou moins à une interface Fruit et 2 à Couleur) et tu vas "étendre" (ou >>>> encapsuler) à la volée chaque JSON/XML que tu reçois. Enfin, si tu as une >>>> méthode qui a besoin d'une couleur+d'un fruit, alors il te faudra peut-être >>>> une classe/méthode/fonction qui se base sur ces deux valeurs. En clair, >>>> DCI/Contextes permet de sélectionner quelles méthodes sont applicables sur >>>> quelle état des données d'entrées. >>>> >>>> Dans le cas où tu as un framework web tel que Rails qui, pour ton bien, >>>> fait le job d'encapsuler les requêtes dans le modèle correspondant au >>>> contenu des données (l'URL), ça ne semble pas universellement judicieux de >>>> refaire cette partie du travail. Je te conseille de démarrer "fat model" >>>> puis de modulariser progressivement en faisant juste des module MyModule >>>> ... >>>> end autour des méthodes qui sont liées (souvent une grosse méthode plein de >>>> if/then et une panoplie de "one-line-helpers" genre >>>> is_machin_chose?(bidule)). >>>> >>>> In fine, le but est de router les bonnes data aux bonnes méthodes et DCI >>>> peut servir, fais confiance à ton XP/flair, des fois le truc genre "gros >>>> sale avec des if et des else et des variables locales comparées à des >>>> variables d'instances" est pertinent si tu ne trouves pas de moyen immédiat >>>> de rendre ton code plus propre. Faire du Ruby ça demande de savoir fuir les >>>> problèmes par la première porte de sortie, ce qui est très difficile quand >>>> on est curieux (c'est du vécu). L'important c'est de se mettre un TODO: >>>> refactor XYZ et d'avoir la discipline pour revenir dessus. D'expérience, >>>> quand on a ce genre de questionnements quand on code c'est que soit le >>>> cerveau n'est plus très frais (i.e., oui, on devient vraiment >>>> temporairement >>>> plus con) soit on a l'impression d'avoir beaucoup de temps devant soi et >>>> qu'on peut se permettre de procrastiner-positivement. Dans le second cas, >>>> mets toi une deadline (en t'autorisant un peu de recherche perso pour >>>> gagner >>>> un peu d'XP). Dans le premier cas, autant passer son temps sur des >>>> problèmes >>>> moins intellectuellement difficiles mais tout aussi important/utiles pour >>>> le >>>> projet, genre demander à un tiers si la couleur du titre lui semble laide >>>> (ce qui risque d'avoir un impact plus important sur ton projet que si tu >>>> utilises extend ou machin.new(chose)). >>>> >>>> Let me know si ça résonne un peu en toi :). >>>> >>>> --Lucas, donneur de coup de pieds au cul à toute heure :P >>>> >>>> >>>> Le 3 juin 2013 21:35, Simon Courtois <[email protected]> a écrit : >>>> >>>>> 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]> 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]> 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) >>>>> > 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 . >>>>> >>>>> >>>>> >>>>> -- >>>>> -- >>>>> 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 . >>>>> >>>>> >>>>> >>>>> >>>>> -- >>>>> -- >>>>> 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 . >>>>> >>>>> >>>>> >>>>> >>>>> -- >>>>> -- >>>>> 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 . >>>>> >>>>> >>>>> >>>>> >>>>> -- >>>>> -- >>>>> 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 . >>>>> >>>>> >>>> >>>> >>>> -- >>>> -- >>>> 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 . >>>> >>>> >>> >>> >>> -- >>> -- >>> 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 . >>> >>> >> >> >> -- >> -- >> 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 . >> >> > > > -- > -- > 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 . > > -- Nicolas Blanco, Web developper http://www.nicolasblanco.fr Jabber/GoogleTalk : [email protected] Twitter : http://twitter.com/slainer68 Github : http://github.com/slainer68 Skype : slainer68 -- -- 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 .
