<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Sukria.net &#187; ORM</title>
	<atom:link href="http://www.sukria.net/fr/archives/tag/orm/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.sukria.net/fr</link>
	<description>I will press many keys on my keyboard causing an implementation to occur.</description>
	<lastBuildDate>Wed, 18 Jan 2012 17:11:38 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>De la bonne façon de manipuler le temps avec Coat::Persistent</title>
		<link>http://www.sukria.net/fr/archives/2009/06/16/de-la-bonne-facon-de-manipuler-le-temps-avec-coatpersistent/</link>
		<comments>http://www.sukria.net/fr/archives/2009/06/16/de-la-bonne-facon-de-manipuler-le-temps-avec-coatpersistent/#comments</comments>
		<pubDate>Tue, 16 Jun 2009 16:41:40 +0000</pubDate>
		<dc:creator>sukria</dc:creator>
				<category><![CDATA[Main]]></category>
		<category><![CDATA[Coat]]></category>
		<category><![CDATA[Coat::Persistent]]></category>
		<category><![CDATA[ORM]]></category>
		<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">http://www.sukria.net/fr/?p=1103</guid>
		<description><![CDATA[Soit la situation suivante : vous avez une classe qui modélise une table de votre base de données. Cette classe possède un champ de type date. Comment faire pour pouvoir utiliser côté Perl, un timestamp et stocker en base une date formatée pour la base de données ? C&#8217;est le problème que je me suis &#8230; <a href="http://www.sukria.net/fr/archives/2009/06/16/de-la-bonne-facon-de-manipuler-le-temps-avec-coatpersistent/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Soit la situation suivante : vous avez une classe qui modélise une table de votre base de données. Cette classe possède un champ de type date. </p>
<p>Comment faire pour pouvoir utiliser côté Perl, un timestamp et stocker en base une date formatée pour la base de données ?</p>
<p>C&#8217;est le problème que je me suis posé récemment avec Coat::Persistent. Plus exactement, ce problème s&#8217;est posé presque de lui-même pendant ma <a title="voir la vidéo de la présentation" href="http://fpw2009.ubicast.eu/videos/free/63/">présentation aux Journées Perl 2009</a>, suite à une question du public. </p>
<p>En fait, je n&#8217;avais que la moitié de la solution, et depuis, je me suis pris d&#8217;un défi pour résoudre correctement ce problème avec Coat::Persistent.</p>
<p>Je vous propose de voir ensemble comment faire.</p>
<p><strong>Objectifs</strong></p>
<ul>
<li>Utiliser le champ date comme un entier dans le code Perl</li>
<li>Ne pas avoir a se soucier de son format de stockage</li>
</ul>
<p>Dans sa version actuelle, Coat::Persistent ne fait pas de différence entre la valeur assignée a un attribut d&#8217;un objet et celle stockée en base. Il nous est donc impossible de réaliser notre objectif de manière élégante sans modifier Coat::Persistent.</p>
<p>La bonne façon de permettre cette fonctionnalité serait donc de dire qu&#8217;un attribut peut avoir un type propre (isa) et un type de stockage. On aurait donc quelquechose comme ça : </p>
<pre class="prettyprint">
has_p created_at => (
    is => 'rw',
    isa => 'Int',
    store_as => 'DateTime',
);
</pre>
<p>Un attribut ainsi déclaré serait donc conscient que sa valeur mémoire (celle de l&#8217;objet instancié) est différente de celle stockée en base. Toute la logique de conversion qu&#8217;elle soit dans un sens ou dans l&#8217;autre serait donc gérée par Coat::Persistent, et non pas par l&#8217;utilisateur.</p>
<p>Tout cela est réalisable en utilisant une <em>coercition bi-directionnelle</em>. Derrière ce mot barbare se cache un principe finalement assez simple : <strong>une valeur x doit être convertible d&#8217;un type A vers un type B, et reciproquement.</strong></p>
<p>Coat permet de définir des coeriction via le mécanisme de types utilisateurs. La subtilité est donc de :</p>
<ul>
<li>Avoir une coercition de définie pour pouvoir convertir une valeur <em>du type de l&#8217;attribut</em> vers une valeur <em>du type de stockage</em> (qui interviendra avant un <code>save</code>)</li>
<li>Avoir une coercition de définie pour pouvoir convertir une valeur du <em>type de stockage</em> vers une valeur <em>du type de l&#8217;attribut</em> (qui interviendra après un <code>find</code>)</li>
</ul>
<p>Voyons maintenant comment écrire ces types et leur règle de coercition respectives pour le coupe Int,DateTime</p>
<p>Nous allons commencer par définir le type DateTime que nous voulons utiliser pour représenter le format de stockage des date dans une table MySQL (YYYY-MM-DD HH:MM:SS).</p>
<pre class="prettyprint">
subtype 'DateTime'
    => as 'Str'
    => where { /^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d$/ };
</pre>
<p>Un attribut de type DateTime est donc un attribut de type Str et dont la valeur respecte la regexp fournie.<br />
Maintenant il nous faut écire la règle de conversion d&#8217;une valeur Int vers une valeur DateTime :</p>
<pre class="prettyprint">
coerce 'DateTime'
    => from 'Int'
    => via {
        my ($sec, $min, $hour, $day, $mon, $year) =
            localtime($_);
        $year += 1900;
        $mon++;
        $day = sprintf('%02d', $day);
        $mon = sprintf('%02d', $mon);
        $hour = sprintf('%02d', $hour);
        $min = sprintf('%02d', $min);
        $sec = sprintf('%02d', $sec);
        return "$year-$mon-$day $hour:$min:$sec";
    };
</pre>
<p>Le type Int est un type standard, nous n&#8217;avons donc pas besoin de le définir. Nous avons seulement besoin de mettre en place une coercition depuis le type DateTime vers le type Int :</p>
<pre class="prettyprint">
coerce 'Int'
    => from 'DateTime'
    => via {
        my ($year, $mon, $day, $hour, $min, $sec) =
             /^(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)$/;
        $year -= 1900;
        $mon--;
        return mktime(
            int($sec), int($min), int($hour),
            $day, $mon, $year);
    };
</pre>
<p>Bien, tout ce code est intéressant, mais est-ce réellement à l&#8217;utilisateur de l&#8217;ORM de le définir ? Je ne crois pas, sa place serait idéale dans un jeu de types prédéfinis. </p>
<p>Pourquoi pas proposer une module <code>Coat::Persistent::Types</code> avec tous les types nécessaires ? Cela me semble bien plus élégant.</p>
<p>Imaginons donc que les types et coercitions définis ci-dessus seraient présents dans, <code>Coat::Persistent::Types::MySQL</code>. Le type pourrait même se nommer <code>'MySQL:DateTime'</code> au lieu de <code>'DateTime'</code>.</p>
<p>L&#8217;utilisateur pourrait donc faire tout simplement :</p>
<pre class="prettyprint">
package Stuff;
use Coat;
use Coat::Persistent;
use Coat::Persistent::Types::MySQL;

has_p created_at => (
    isa => 'Int',
    store_as => 'MySQL:DateTime',
);
</pre>
<p>Et le tour serait joué !</p>
<p>Il ne resterait alors qu&#8217;une seule chose à faire : patcher la mécanique de sauvegarde de Coat::Persistent pour que les valeurs utilisées dans le SQL puissent être converties si nécessaire. </p>
<p>Cela peut se faire très simplement en introduisant la notion de <em>valeur de stockage</em>. Cette valeur serait égale à celle de l&#8217;attribut si aucun <code>store_as</code> n&#8217;est défini, elle serait égale à la coercition adéquate sinon.</p>
<p>Bien, maintenant que ce problème est résolu, il ne me reste plus qu&#8217;à patcher Coat::Persistent et à publier une nouvelle version avec toutes ces bonnes calories intellectuelles&#8230;</p>
<div id='teoShare' ><div id='teo2Google'>
		<!-- Place this tag where you want the +1 button to render -->
		<g:plusone size='tall' annotation='none'></g:plusone>

		<!-- Place this render call where appropriate -->
		<script type='text/javascript'>
		  (function() {
			var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
			po.src = 'https://apis.google.com/js/plusone.js';
			var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
		  })();
		</script>
		</div><div id="teoTweet" >
		<a href="http://twitter.com/share" class="twitter-share-button" data-count="none" data-via="sukria">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script> </div></div><div style="height:0px; width:0px; overflow:hidden;"><a href="http://www.zeitblog.com/?in=plugin">blog tools and plugins from www.zeitblog.com</a></div><p>Related posts:<ol>
<li><a href='http://www.sukria.net/fr/archives/2009/06/19/publication-de-coatpersistent-0200/' rel='bookmark' title='Publication de Coat::Persistent 0.200'>Publication de Coat::Persistent 0.200</a> <small>Je viens d&#8217;uploader Coat::Persistent sur CPAN. Voila une bonne chose...</small></li>
<li><a href='http://www.sukria.net/fr/archives/2007/10/12/coat-persistent/' rel='bookmark' title='Coat Persistent'>Coat Persistent</a> <small>La famille de Coat s&#8217;agrandit, voici un premier essai de...</small></li>
<li><a href='http://www.sukria.net/fr/archives/2007/12/03/nouvelle-fonctionnalite-pour-coatpersistent-__package__-enable_cache/' rel='bookmark' title='Nouvelle fonctionnalité pour Coat::Persistent : cache'>Nouvelle fonctionnalité pour Coat::Persistent : cache</a> <small>Une nouvelle fonctionnalité va faire son apparition d&#8217;ici peu de...</small></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.sukria.net/fr/archives/2009/06/16/de-la-bonne-facon-de-manipuler-le-temps-avec-coatpersistent/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Nouvelle fonctionnalité pour Coat::Persistent : cache</title>
		<link>http://www.sukria.net/fr/archives/2007/12/03/nouvelle-fonctionnalite-pour-coatpersistent-__package__-enable_cache/</link>
		<comments>http://www.sukria.net/fr/archives/2007/12/03/nouvelle-fonctionnalite-pour-coatpersistent-__package__-enable_cache/#comments</comments>
		<pubDate>Mon, 03 Dec 2007 15:05:24 +0000</pubDate>
		<dc:creator>sukria</dc:creator>
				<category><![CDATA[Main]]></category>
		<category><![CDATA[Coat]]></category>
		<category><![CDATA[ORM]]></category>
		<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">http://www.sukria.net/fr/archives/2007/12/03/nouvelle-fonctionnalite-pour-coatpersistent-__package__-enable_cache/</guid>
		<description><![CDATA[Une nouvelle fonctionnalité va faire son apparition d&#8217;ici peu de temps dans Coat::Persistent : la possibilité de cacher les résultats des requêtes SQL exécutées. Le cache est géré par l&#8217;excellent Cache::FastMmap. Coat::Persistent proposera une interface simple pour activer le cache : Coat::Persistent->enable_cache( expire_time => '1h', cache_size => '50m', share_file => '/var/cache/apache/sites/www.monsite.cache', ); Comme chaque option &#8230; <a href="http://www.sukria.net/fr/archives/2007/12/03/nouvelle-fonctionnalite-pour-coatpersistent-__package__-enable_cache/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Une nouvelle fonctionnalité va faire son apparition d&#8217;ici peu de temps dans <a href="http://search.cpan.org/perldoc?Coat::Persistent">Coat::Persistent</a> : la possibilité de cacher les résultats des requêtes SQL exécutées.</p>
<p>Le cache est géré par l&#8217;excellent <a href="http://search.cpan.org/perldoc?Cache::FastMmap">Cache::FastMmap</a>. Coat::Persistent proposera une interface simple pour activer le cache :</p>
<pre>
Coat::Persistent->enable_cache(
    expire_time => '1h',
    cache_size  => '50m',
    share_file  => '/var/cache/apache/sites/www.monsite.cache',
);
</pre>
<p>Comme chaque option de configuration fournie par Coat::Persistent, le cache peut être activé ou non pour une classe donnée ou pour toutes les classes (ce qui veut dire qu&#8217;on peut même immaginer avoir des caches différents par classe).</p>
<p>Du coup, c&#8217;est <a href="http://www.libellaris.fr">Libellaris.fr</a> qui a pris un speed.</p>
<p>A suivre sur le CPAN donc (c&#8217;est déjà dans le SVN).</p>
<div id='teoShare' ><div id='teo2Google'>
		<!-- Place this tag where you want the +1 button to render -->
		<g:plusone size='tall' annotation='none'></g:plusone>

		<!-- Place this render call where appropriate -->
		<script type='text/javascript'>
		  (function() {
			var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
			po.src = 'https://apis.google.com/js/plusone.js';
			var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
		  })();
		</script>
		</div><div id="teoTweet" >
		<a href="http://twitter.com/share" class="twitter-share-button" data-count="none" data-via="sukria">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script> </div></div><div style="height:0px; width:0px; overflow:hidden;"><a href="http://www.zeitblog.com/?in=plugin">blog tools and plugins from www.zeitblog.com</a></div><p>Related posts:<ol>
<li><a href='http://www.sukria.net/fr/archives/2007/10/12/coat-persistent/' rel='bookmark' title='Coat Persistent'>Coat Persistent</a> <small>La famille de Coat s&#8217;agrandit, voici un premier essai de...</small></li>
<li><a href='http://www.sukria.net/fr/archives/2009/06/06/nouvelle-version-de-coatpersistent-0104/' rel='bookmark' title='Nouvelle version de Coat::Persistent : 0.104'>Nouvelle version de Coat::Persistent : 0.104</a> <small>En travaillant sur mes slides pour FPW 2009, je me...</small></li>
<li><a href='http://www.sukria.net/fr/archives/2009/06/16/de-la-bonne-facon-de-manipuler-le-temps-avec-coatpersistent/' rel='bookmark' title='De la bonne façon de manipuler le temps avec Coat::Persistent'>De la bonne façon de manipuler le temps avec Coat::Persistent</a> <small>Soit la situation suivante : vous avez une classe qui...</small></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.sukria.net/fr/archives/2007/12/03/nouvelle-fonctionnalite-pour-coatpersistent-__package__-enable_cache/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Coat Persistent</title>
		<link>http://www.sukria.net/fr/archives/2007/10/12/coat-persistent/</link>
		<comments>http://www.sukria.net/fr/archives/2007/10/12/coat-persistent/#comments</comments>
		<pubDate>Fri, 12 Oct 2007 16:53:30 +0000</pubDate>
		<dc:creator>sukria</dc:creator>
				<category><![CDATA[Main]]></category>
		<category><![CDATA[Coat]]></category>
		<category><![CDATA[ORM]]></category>
		<category><![CDATA[Perl]]></category>

		<guid isPermaLink="false">http://www.sukria.net/fr/archives/2007/10/12/coat-persistent/</guid>
		<description><![CDATA[La famille de Coat s&#8217;agrandit, voici un premier essai de mélange des concepts de l&#8217;ORM de Rails avec la meta-classe Coat : Coat::Persistent. Tweet blog tools and plugins from www.zeitblog.comRelated posts: Nouvelle fonctionnalité pour Coat::Persistent : cache Une nouvelle fonctionnalité va faire son apparition d&#8217;ici peu de... De la bonne façon de manipuler le temps &#8230; <a href="http://www.sukria.net/fr/archives/2007/10/12/coat-persistent/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>La famille de Coat s&#8217;agrandit, voici un premier essai de mélange des concepts de l&#8217;ORM de Rails avec la meta-classe Coat : <a href="http://search.cpan.org/~sukria/Coat-Persistent-0.0_0.1/lib/Coat/Persistent.pm">Coat::Persistent</a>.</p>
<div id='teoShare' ><div id='teo2Google'>
		<!-- Place this tag where you want the +1 button to render -->
		<g:plusone size='tall' annotation='none'></g:plusone>

		<!-- Place this render call where appropriate -->
		<script type='text/javascript'>
		  (function() {
			var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
			po.src = 'https://apis.google.com/js/plusone.js';
			var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
		  })();
		</script>
		</div><div id="teoTweet" >
		<a href="http://twitter.com/share" class="twitter-share-button" data-count="none" data-via="sukria">Tweet</a><script type="text/javascript" src="http://platform.twitter.com/widgets.js"></script> </div></div><div style="height:0px; width:0px; overflow:hidden;"><a href="http://www.zeitblog.com/?in=plugin">blog tools and plugins from www.zeitblog.com</a></div><p>Related posts:<ol>
<li><a href='http://www.sukria.net/fr/archives/2007/12/03/nouvelle-fonctionnalite-pour-coatpersistent-__package__-enable_cache/' rel='bookmark' title='Nouvelle fonctionnalité pour Coat::Persistent : cache'>Nouvelle fonctionnalité pour Coat::Persistent : cache</a> <small>Une nouvelle fonctionnalité va faire son apparition d&#8217;ici peu de...</small></li>
<li><a href='http://www.sukria.net/fr/archives/2009/06/16/de-la-bonne-facon-de-manipuler-le-temps-avec-coatpersistent/' rel='bookmark' title='De la bonne façon de manipuler le temps avec Coat::Persistent'>De la bonne façon de manipuler le temps avec Coat::Persistent</a> <small>Soit la situation suivante : vous avez une classe qui...</small></li>
<li><a href='http://www.sukria.net/fr/archives/2009/06/19/publication-de-coatpersistent-0200/' rel='bookmark' title='Publication de Coat::Persistent 0.200'>Publication de Coat::Persistent 0.200</a> <small>Je viens d&#8217;uploader Coat::Persistent sur CPAN. Voila une bonne chose...</small></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.sukria.net/fr/archives/2007/10/12/coat-persistent/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

