<?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>XykoX</title>
	<atom:link href="http://blog.xykox.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.xykox.net</link>
	<description>Ruby On Rails, Javascript, ...</description>
	<lastBuildDate>Sat, 19 Nov 2011 07:23:06 +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>Cracker une clé MD5 &#8230;</title>
		<link>http://blog.xykox.net/2011/11/19/cracker-une-cle-md5/</link>
		<comments>http://blog.xykox.net/2011/11/19/cracker-une-cle-md5/#comments</comments>
		<pubDate>Sat, 19 Nov 2011 07:23:06 +0000</pubDate>
		<dc:creator>jean-marc</dc:creator>
				<category><![CDATA[Non classé]]></category>

		<guid isPermaLink="false">http://blog.xykox.net/?p=133</guid>
		<description><![CDATA[&#8230; rien de plus simple avec BozoCarck qui utilise une recherche sur Google. Et encore mieux, il y a Md5This, si vous ne voulez/pouvez utiliser BozoCrack. &#160;]]></description>
			<content:encoded><![CDATA[<p>&#8230; rien de plus simple avec <a href="https://github.com/juuso/BozoCrack">BozoCarck</a> qui utilise une recherche sur Google. Et encore mieux, il y a <a href="http://www.md5this.com/">Md5This</a>, si vous ne voulez/pouvez utiliser BozoCrack.</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.xykox.net/2011/11/19/cracker-une-cle-md5/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Boilerplate : HTML5 et bonnes pratiques</title>
		<link>http://blog.xykox.net/2011/05/27/boilerplate-html5-et-bonnes-pratiques/</link>
		<comments>http://blog.xykox.net/2011/05/27/boilerplate-html5-et-bonnes-pratiques/#comments</comments>
		<pubDate>Fri, 27 May 2011 08:58:26 +0000</pubDate>
		<dc:creator>jean-marc</dc:creator>
				<category><![CDATA[Non classé]]></category>

		<guid isPermaLink="false">http://blog.xykox.net/?p=113</guid>
		<description><![CDATA[Voici un framework CSS qui vaut le coup d&#8217;oeil, surtout pour ceux comme moi qui n&#8217;ont pas encore bien stabilisé les bonnes pratiques avec HTML5 : Boilerplate. Bien que je ne sois pas fan des frameworks CSS, celui ci à &#8230; <a href="http://blog.xykox.net/2011/05/27/boilerplate-html5-et-bonnes-pratiques/">Continuer la lecture <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.xykox.net/wp-content/uploads/2011/05/html5boilerplate.png"><span style="color: #888888;"><img class="size-medium wp-image-114 alignright" title="html5boilerplate" src="http://blog.xykox.net/wp-content/uploads/2011/05/html5boilerplate-300x202.png" alt="" width="300" height="202" /></span></a>Voici un framework CSS qui vaut le coup d&#8217;oeil, surtout pour ceux comme moi qui n&#8217;ont pas encore bien stabilisé les bonnes pratiques avec HTML5 : <a href="http://html5boilerplate.com/">Boilerplate</a>.</p>
<p>Bien que je ne sois pas fan des frameworks CSS, celui ci à l&#8217;avantage de se présenter sous différente forme et surtout assez didactique. J&#8217;avoue je n&#8217;ai pas passé au crible tous les frameworks CSS, mais au premier coup d&#8217;oeil celui ci me paraît valoir le coup.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.xykox.net/2011/05/27/boilerplate-html5-et-bonnes-pratiques/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Intégration HTML avec nanoc</title>
		<link>http://blog.xykox.net/2011/01/14/integration-html-avec-nanoc/</link>
		<comments>http://blog.xykox.net/2011/01/14/integration-html-avec-nanoc/#comments</comments>
		<pubDate>Fri, 14 Jan 2011 09:18:19 +0000</pubDate>
		<dc:creator>jean-marc</dc:creator>
				<category><![CDATA[Web Dev]]></category>

		<guid isPermaLink="false">http://blog.xykox.net/?p=101</guid>
		<description><![CDATA[Encore un petit outil sympathique fait en Ruby : nanoc. Nanoc est un outil qui permet de réaliser un site web statique. D&#8217;ailleurs leur site est réalisé avec nanoc et vous pouvez télécharger les sources Mais pour ma part je &#8230; <a href="http://blog.xykox.net/2011/01/14/integration-html-avec-nanoc/">Continuer la lecture <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Encore un petit outil sympathique fait en Ruby : <a href="http://nanoc.stoneship.org/">nanoc</a>.<br />
Nanoc est un outil qui permet de réaliser un site web statique. D&#8217;ailleurs <a href="http://projects.stoneship.org/trac/nanoc/wiki/Samples/NanocSite">leur site est réalisé avec nanoc et vous pouvez télécharger les sources<br />
</a></p>
<p>Mais pour ma part je préfère l&#8217;utiliser dans le cas d&#8217;intégration HTML et que je dois livrer à des clients une version statique. Comme les frameworks MVC évolués, il gère un layout, des partial.</p>
<p><a href="http://nanoc.stoneship.org/docs/2-installation/">pour l&#8217;installation de nanoc</a>, un petit coup de gem :</p>
<pre class="brush: bash; title: ; notranslate">
$ gem install nanoc
</pre>
<p>pour commencer le site, avec toute l&#8217;architecture :</p>
<pre class="brush: bash; title: ; notranslate">
$ nanoc create_site monsite
      create  config.yaml
      create  Rakefile
      create  Rules
      create  content/index.html
      create  content/stylesheet.css
      create  layouts/default.html
Created a blank nanoc site at 'monsite'. Enjoy!

$ cd monsite
$ ls -l
-rw-r--r-- 1 1000 1000 2090 mai 27 10:18 config.yaml
drwxr-xr-x 2 1000 1000 4096 mai 27 10:18 content
drwxr-xr-x 2 1000 1000 4096 mai 27 10:18 layouts
drwxr-xr-x 2 1000 1000 4096 mai 27 10:18 lib
drwxr-xr-x 2 1000 1000 4096 mai 27 10:18 output
-rw-r--r-- 1 1000 1000   22 mai 27 10:18 Rakefile
-rw-r--r-- 1 1000 1000  692 mai 27 10:18 Rules
</pre>
<p>Ensuite soit vous voulez une version statique de votre site :</p>
<pre class="brush: bash; title: ; notranslate">
$ nanoc compile
Loading site data...
Compiling site...
      create  [0.00s]  output/style.css
      create  [0.04s]  output/index.html

Site compiled in 0.21s.
</pre>
<p>ok mais moi, je veux développer, intégrer, modifier sans avoir à recompiler .. bah il y a le autocompile.<br />
L&#8217;option autocompile lance un serveur web (comme webrick avec rails) et à chaque requête vérifie les timestamps des fichiers, recompile si nécéssaire et envoie la version statique via le serveur web.</p>
<pre class="brush: bash; title: ; notranslate">
$ nanoc autocompile
Running on http://0.0.0.0:3000/
</pre>
<p>Il suffit de regarder dans le navigateur à l&#8217;adresse http://0.0.0.0:3000/ et comme ça ldéveloppeur Rails n&#8217;est pas dépaysé !</p>
<p>Si vous ne souhaitez pas utiliser l&#8217;autocompile et encore moins le compile, mais juste voir le site via un serveur web rapidement il y la commande view :</p>
<pre class="brush: bash; title: ; notranslate">
$ nanoc view
Running on http://0.0.0.0:3000/
</pre>
<p>Bon ça c&#8217;est le <a href="http://nanoc.stoneship.org/docs/3-getting-started/">cas simple du tutoriel</a>. Pour réaliser l&#8217;intégration, j&#8217;ai du apporter mon lot de configuration tiré des sources du site de nanoc lui-même :</p>
<p>Il faut faut savoir que tout ce qui est dans content et layout est compilé par nanoc, et donc peut modifier les feuilles de style, déplacer les images.</p>
<p>Personnellement, je veux juste qu&#8217;il me génère mes pages HTML. J&#8217;ai donc mis mes feuilles de style et toutes les images de style et autre fichiers JS dans un dossier static</p>
<pre class="brush: bash; title: ; notranslate">
$ cd monsite
$ mkdir static
</pre>
<p>Editer le fichier config.yaml et ajouter le dossier static comme étant de type &#8216;static&#8217;</p>
<pre class="brush: ruby; title: ; notranslate">
  ....
    layouts_root: /
  -
    type: static
    items_root: /static/
</pre>
<p>le type static n&#8217;existe pas dans nanoc. Il faut le déclarer soit-même et créer un data_source. Dans le dossier lib/data_sources, il faut créer le fichier static.rb :</p>
<pre class="brush: ruby; title: ; notranslate">
require 'digest'

module Nanoc3::DataSources

  class Static &lt; Nanoc3::DataSource

    identifier :static

    def items
      # Get prefix
      prefix = config[:prefix] || 'static'

      # Get all files under prefix dir
      filenames = Dir[prefix + '/**/*'].select { |f| File.file?(f) }

      # Convert filenames to items
      filenames.map do |filename|
        attributes = {
          :extension =&gt; File.extname(filename)[1..-1],
          :filename  =&gt; filename,
        }
        identifier = filename[(prefix.length+1)..-1] + '/'

        mtime      = File.mtime(filename)
        checksum   = checksum_for(filename)

        Nanoc3::Item.new(
          filename,
          attributes,
          identifier,
          :binary =&gt; true, :mtime =&gt; mtime, :checksum =&gt; checksum
        )
      end
    end

  private

    # Returns a checksum of the given filenames
    # TODO un-duplicate this somewhere
    def checksum_for(*filenames)
      filenames.flatten.map do |filename|
        digest = Digest::SHA1.new
        File.open(filename, 'r') do |io|
          until io.eof
            data = io.readpartial(2**10)
            digest.update(data)
          end
        end
        digest.hexdigest
      end.join('-')
    end

  end

end
</pre>
<p>Ce qui aura pour effet que de copier les fichiers dans le dossier output sans traitement particulier.<br />
Note : Ce fichier est contenu dans les sources du site nanoc.</p>
<p>Il faut également modifier le fichier Rules, qui sert traiter les routes et à indiquer quels dossiers et fichiers doivent être compilé (vous pouvez compiler également des feuilles de style) :</p>
<pre class="brush: ruby; title: ; notranslate">
#!/usr/bin/env ruby

route '/static/*' do
  # /static/foo.html/ → /foo.html
  item.identifier[7..-2]
end

compile '/static/*' do
end

compile '/stylesheet/' do
  # don’t filter or layout
end

compile '*' do
  filter :erb
  layout 'default'
end

route '/stylesheet/' do
  '/style.css'
end

route '*' do
  item.identifier + 'index.html'
end

layout '*', :erb
</pre>
<p>Maintenant vous pouvez travailler sur le layout :layouts/default.html, et sur le contenu d&#8217;une page : content/index.html.</p>
<p>Pour réaliser un partial style Rails :</p>
<ol>
<li>dans layouts, crééer le fichier : monpartial.html.erb</li>
<li>dans la page de content :
<pre class="brush: ruby; title: ; notranslate">
&lt;%= render 'monpartial' %&gt;
</pre>
</li>
</ol>
<p>Voilà au moins le minimum pour pouvoir intégrer sereinement, et en plus vous êtes plusieurs sur l&#8217;intégration (ce qui est rare) SVN ou Git sont vos amis.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.xykox.net/2011/01/14/integration-html-avec-nanoc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Web spider (ou aspiration de site) avec Anemone &#8230;</title>
		<link>http://blog.xykox.net/2010/12/11/web-spider-ou-aspiration-de-site-avec-anemone/</link>
		<comments>http://blog.xykox.net/2010/12/11/web-spider-ou-aspiration-de-site-avec-anemone/#comments</comments>
		<pubDate>Sat, 11 Dec 2010 16:32:48 +0000</pubDate>
		<dc:creator>jean-marc</dc:creator>
				<category><![CDATA[Web Dev]]></category>

		<guid isPermaLink="false">http://blog.xykox.net/?p=91</guid>
		<description><![CDATA[J&#8217;ai besoin une version de quelques sites réalisés avec Rails en version statique pour une présentation offline. J&#8217;aurai pu utiliser wget, mais franchement j&#8217;avais envie et besoin d&#8217;un outil plus personnalisable. Ou bien étendre les controller pour récupérer la sortie &#8230; <a href="http://blog.xykox.net/2010/12/11/web-spider-ou-aspiration-de-site-avec-anemone/">Continuer la lecture <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>J&#8217;ai besoin une version de quelques sites réalisés avec Rails en version statique pour une présentation offline.<br />
J&#8217;aurai pu utiliser wget, mais franchement j&#8217;avais envie et besoin d&#8217;un outil plus personnalisable. Ou bien étendre les controller pour récupérer la sortie mais trop de problème et pas assez de souplesse. C&#8217;est là qu&#8217;intervient <a href="http://anemone.rubyforge.org/">Anemone</a>.</p>
<p>La mise en place est simple (via gem bien sûr), et la prise en main l&#8217;est tout autant, comme le montre l&#8217;exmple de leur site :</p>
<pre class="brush: ruby; title: ; notranslate">
require 'anemone'

Anemone.crawl(&quot;http://www.example.com/&quot;) do |anemone|
  anemone.on_every_page do |page|
      puts page.url
  end
end
</pre>
<p>C&#8217;est assez rudimentaire, mais en couplant avec des outils puissant comme <a href="http://hpricot.com/">Hpricot</a>, et une surcharge de la classe URI, on en sort un outil vraiment personnalisé et puissant.</p>
<p>J&#8217;ai pu réécrire les chemins statiques de mon code en chemin relatif pour une visualisation offline en surchargeant la classe URI </p>
<pre class="brush: ruby; title: ; notranslate">

require 'uri'
require 'rubygems'
require 'anemone'
require 'hpricot'

OUTPUT_DIR = File.join(File.dirname(__FILE__), 'export', 'sites')

module UriExt

  def last_item_of_path_is_used_for_filename
    self.query || (File.basename(self.path) =~ /^(.*)\..*$/)
  end

  def to_static_filename
    filename = ''
    if self.query
      if (File.basename(self.path) =~ /^(.*)\..*$/)
        filename = $1
      else
        filename = File.basename(self.path)
      end
      filename += '-' + self.query_to_filename_ext + '.html'
    else
      if (File.basename(self.path) =~ /^(.*)\..*$/)
        filename = File.basename(self.path)
      else
        filename = 'index.html'
      end
    end
    filename
  end

  def query_to_filename_ext
    self.query ? self.query.gsub(/[=;&amp;]/, '-') : nil
  end

  def build_relative_path(with_host=true)
    if self.path !~ /^\/$/
      items = with_host ? [self.host] : []
      original_path = (self.path =~ /^\/(.*)$/ ? $1 : self.path)
      items_original_path =  original_path.split('/')
      items_original_path.shift if items_original_path.first == '/'
      items_original_path.pop if self.last_item_of_path_is_used_for_filename
      items += items_original_path
      File.join(items)
    end
  end

  def complete_path_filename(with_host=true)
    items = []
    relative_path = self.build_relative_path(with_host)
    items &lt;&lt; relative_path if relative_path
    items &lt;&lt; self.to_static_filename
    File.join(items)
  end

  def create_dir
    relative_path = self.build_relative_path
    if relative_path
      FileUtils.mkdir_p(File.join(OUTPUT_DIR, relative_path))
    end
  end

  def create_file(content)
    self.create_dir
    File.open(File.join(OUTPUT_DIR, self.complete_path_filename), 'w') do |file|
      file.write(content)
    end
  end

  def build_relative_path_for_html
    if self.path !~ /^\/$/
      (self.path =~ /^\/(.*)$/ ? $1 : self.path)
    else
      'index.html'
    end
  end

  def root_back_relative_path(an_absloute_path)
    if self.path !~ /^\/$/
      return File.join((['..'] * ((self.path.split('/')).length - 1)).join('/'), (an_absloute_path =~ /^\/(.*)$/ ? $1 : an_absloute_path))
    else
      (an_absloute_path =~ /^\/(.*)$/ ? $1 : an_absloute_path)
    end
  end
end

URI::HTTP.send(:include, UriExt)
URI::Generic.send(:include, UriExt)

Anemone.crawl(&quot;http://www.example.com&quot;) do |anemone|
  # cache pages
  anemone.storage = Anemone::Storage.PStore('arnaudkozlinski.pstore')

  # avoid JPG crawl (just a particular case for my website)
  # it's here only for th example
  anemone.focus_crawl { |page| page.links.select{ |uri| uri.path !~ /\.(jpg|JPG)$/ } }

  anemone.on_every_page do |page|
      puts page.url
      # if craw a html page parse and modify it with Hpricot
      if page.headers['content-type'].join('') =~ /^text\/html/
        doc = Hpricot(page.body)

        # image source rewriting
        doc.search('img').each do |img|
          if img.attributes['src']
            uri_img = URI.parse(img.attributes['src'])
            img['src'] =  page.url.root_back_relative_path(uri_img.path)
          end
        end
        ....

        # stylesheet source rewriting
        doc.search('link').each do |script|
          if script.attributes['href']
            uri_script = URI.parse(script.attributes['href'])
            script['href'] =  page.url.root_back_relative_path(uri_script.path)
          end
        end
        ....

     end
  end
</pre>
<p>Petit bémol, reste le parsing des feuilles de style CSS pour la réécriture des url() vers les images de style. Mais comme les url des feuilles de style sont déjà en relatif (c&#8217;est ma règle en tout cas), je n&#8217;ai pas eu besoin de parser, juste copier les images au bon endroit. D&#8217;autant que je n&#8217;ai pas trouvé le Hpricot du CSS.</p>
<p>Ça peut paraître long à première vue, mais quand on maîtrise Ruby, c&#8217;est largement moins prise de tête que d&#8217;utiliser un web spider automatique, car il y a toujours des cas particuliers et par expérience aucun ne permet d&#8217;obtenir un résultat parfait.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.xykox.net/2010/12/11/web-spider-ou-aspiration-de-site-avec-anemone/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Rails cache_key et Array</title>
		<link>http://blog.xykox.net/2010/11/11/rails-cache_key-et-array/</link>
		<comments>http://blog.xykox.net/2010/11/11/rails-cache_key-et-array/#comments</comments>
		<pubDate>Thu, 11 Nov 2010 21:21:45 +0000</pubDate>
		<dc:creator>jean-marc</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Web Dev]]></category>

		<guid isPermaLink="false">http://blog.xykox.net/?p=81</guid>
		<description><![CDATA[c&#8217;est bien cache_key pour les ActiveRecord, mais c&#8217;est encore mieux pour les collections d&#8217;ActiveRecord. comme ça, vous pouvez faire une cache key pour un ensemble :]]></description>
			<content:encoded><![CDATA[<p>c&#8217;est bien cache_key pour les ActiveRecord, mais c&#8217;est encore mieux pour les collections d&#8217;ActiveRecord.</p>
<pre class="brush: ruby; title: ; notranslate">
ActiveRecord::Base.class_eval do
  def cache_key_with_extra_keys(*args)
    extra =  args.empty? ? '' :  '-' + args.collect{|a| a.to_s }.join('-')
    cache_key_without_extra_keys + extra
  end
  alias_method_chain :cache_key, :extra_keys
end

Array.class_eval do
  def cache_key(*args)
    keys = []
    self.each do |item|
      keys &lt;&lt; (item.respond_to?(:updated_at) &amp;&amp; item.respond_to?(:id) ? &quot;#{item.id}-#{item.updated_at.to_s(:number)}&quot; : item.object_id.to_s)
    end
    extra =  args.empty? ? '' :  '-' + args.collect{|a| a.to_s }.join('-')
    return keys.join('-') + extra
  end
end
</pre>
<p>comme ça, vous pouvez faire une cache key pour un ensemble :</p>
<pre class="brush: ruby; title: ; notranslate">
last_articles = Article.find(:all,:limit =&gt; 5)
last_articles.cache_key
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.xykox.net/2010/11/11/rails-cache_key-et-array/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>La magie de ruby &#8230;</title>
		<link>http://blog.xykox.net/2010/10/27/la-magie-de-ruby/</link>
		<comments>http://blog.xykox.net/2010/10/27/la-magie-de-ruby/#comments</comments>
		<pubDate>Wed, 27 Oct 2010 14:20:55 +0000</pubDate>
		<dc:creator>jean-marc</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Web Dev]]></category>

		<guid isPermaLink="false">http://blog.xykox.net/?p=69</guid>
		<description><![CDATA[Il y a des jours où vraiment Ruby me simplifie la vie. Ce qui suit n&#8217;est pas révolutionnaire mais je suis tellement content de gagner des heures de codes et de tests grâce à la souplesse de Ruby que je &#8230; <a href="http://blog.xykox.net/2010/10/27/la-magie-de-ruby/">Continuer la lecture <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Il y a des jours où vraiment Ruby me simplifie la vie. Ce qui suit n&#8217;est pas révolutionnaire mais je suis tellement content de gagner des heures de codes et de tests grâce à la souplesse de Ruby que je ne peux m&#8217;empêcher de vous en faire part.</p>
<p>Voici le problème :</p>
<p>Je possède un plugin contenant plusieurs modèles &laquo;&nbsp;métiers&nbsp;&raquo; que j&#8217;utilise dans plusieurs sites/applications.</p>
<p>Et dernièrement, je souhaite ajouter un attribut commun à tous ces modèles. Jusque là rien de bien compliqué, mais juste pour une seule application, c&#8217;est à dire sans avoir d&#8217;impact sur les autres applications.</p>
<p>Ex :<br />
foo.rb :</p>
<pre class="brush: ruby; title: ; notranslate">
class Foo &lt; ActiveRecord::Base
  has_many :bars
end
</pre>
<p>bar.rb :</p>
<pre class="brush: ruby; title: ; notranslate">
class Bar &lt; ActiveRecord::Base
  belongs_to :foo
end
</pre>
<p>Ensuite vous avez une classe qui gère des tas de Foo et de Bar :</p>
<pre class="brush: ruby; title: ; notranslate">
class MyScript

  def initialize(foo_name, bar_name)
    @foo_name = foo_name
    @bar_name = bar_name
  end

  def do_a_lot_things
     ...
     # a lot of things before
     if foo = Foo.find_by_name(@foo_name)
     ...
     end

     if bar = Bar.find_by_name(@bar_name)
      ...
     end
     # a lot of things after
     ...
  end
end
</pre>
<p>ok. maintenant j&#8217;ajoute un champ commun : domain une sorte d&#8217;enum contenant par exemple : ['Sport', 'Economy', 'Culture']</p>
<pre class="brush: ruby; title: ; notranslate">
&gt;&gt; Foo.new.domain = 'Sport'
&gt;&gt; a_bar =Bar.find(:first)
&gt;&gt; a_bar.domain
'Culture'
</pre>
<p>bref simple &#8230; mais je veux cloisonner mon script en fonction du domaine. il faudrait que je fasse :</p>
<pre class="brush: ruby; title: ; notranslate">
class MyScript
  ...
  def do_a_lot_things
     ...
     # a lot of things before
     if foo = Foo.find_by_name_and_domain(@foo_name, @domain)
     ...
     end

     if bar = Bar.find_by_name_and_domaine(@bar_name, @domain)
      ...
     end
     # a lot of things after
     ...
  end
end
</pre>
<p>Ok j&#8217;ai bien fait mes tests, la refactorisation ne devrait pas être compliquée &#8230; ah mais non ! mon code doit être compatible pour les applications qui utilise Foo, Bar et MyScript sans utilser le domaine. </p>
<p>On y arrive .. Heureusement ruby et rails mettent à disposition plusieurs outils qui permettent détendre sans tout casser.</p>
<p>Première piste : alias_method_chain</p>
<pre class="brush: ruby; title: ; notranslate">
            @@domaine = 'Sport'
            ....
             def find_with_domaine(*args)
                find_options = {}
                if @domaine
                  find_options[:conditions] = [ 'domaine = ? ', @@domaine ]
                end
                with_scope(:find =&gt; find_options) do
                  find_without_domaine(*args)
                end
              end
              alias_method_chain :find, :domaine
</pre>
<p>mouais ok mais bon comment fournir le bon domaine pour tous les Foo et Bar utilisés dans MyScript ?</p>
<p>Deuxième piste : une variable de classe mais attention il faut être sûr qu&#8217;elle soit valable uniquement pour le thread, voulant utiliser le hash  Thread.current, j&#8217;ai quand même pris conseil chez <a href="http://coderrr.wordpress.com/2008/04/10/lets-stop-polluting-the-threadcurrent-hash/">coderr pour éviter d&#8217;abuser  du Thread.current</a></p>
<pre class="brush: ruby; title: ; notranslate">
class Class
  def thread_local_accessor name, options = {}
    m = Module.new
    m.module_eval do
      class_variable_set :&quot;@@#{name}&quot;, Hash.new {|h,k| h[k] = options[:default] }
    end
    m.module_eval %{
      FINALIZER = lambda {|id| @@#{name}.delete id }

      def #{name}
        @@#{name}[Thread.current.object_id]
      end

      def #{name}=(val)
        ObjectSpace.define_finalizer Thread.current, FINALIZER  unless @@#{name}.has_key? Thread.current.object_id
        @@#{name}[Thread.current.object_id] = val
      end
    }

    class_eval do
      include m
      extend m
    end
  end
end
</pre>
<p>et j&#8217;étends la classe active_record :</p>
<pre class="brush: ruby; title: ; notranslate">
ActiveRecord::Base.class_eval do
  thread_local_accessor :domain_store, :default =&gt; nil

  class &lt;&lt; self
    def do_actions_with_domain(domain, &amp;block)
      ActiveRecord::Base.domain_store = domain
      yield
      ActiveRecord::Base.domain_store = nil
    end
  end
end
</pre>
<p>Ensuite j&#8217;appelle mon script encadré par do_actions_with_domain</p>
<pre class="brush: ruby; title: ; notranslate">
ActiveRecord::Base.do_actions_with_domain('Economy') do
  MyScript.new('foo_name', 'bar_name').do_a_lot_things
end
</pre>
<p>et voilà pas besoin de modifier ma class MyScript et ça marche au poil, merci Ruby <img src='http://blog.xykox.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.xykox.net/2010/10/27/la-magie-de-ruby/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>TinyMCE 2 et Firefox 3.6.9, import d&#8217;image</title>
		<link>http://blog.xykox.net/2010/09/10/tinymce-2-et-firefox-3-6-9-import-dimage/</link>
		<comments>http://blog.xykox.net/2010/09/10/tinymce-2-et-firefox-3-6-9-import-dimage/#comments</comments>
		<pubDate>Fri, 10 Sep 2010 08:00:06 +0000</pubDate>
		<dc:creator>jean-marc</dc:creator>
				<category><![CDATA[Web Dev]]></category>

		<guid isPermaLink="false">http://blog.xykox.net/?p=59</guid>
		<description><![CDATA[Pour ceux qui n&#8217;ont pas migré le tinymce de leur site vers la version 3, l&#8217;import d&#8217;image ne fonctionne plus pour Firefox 3.6.9. Il suffit de modifier tiny_mce.js, dans la fonction fixGeckoBaseHREFBug :]]></description>
			<content:encoded><![CDATA[<p>Pour ceux qui n&#8217;ont pas migré le tinymce de leur site vers la version 3, l&#8217;import d&#8217;image ne fonctionne plus pour Firefox 3.6.9.  Il suffit de modifier  tiny_mce.js, dans la fonction fixGeckoBaseHREFBug :</p>
<pre class="brush: jscript; title: ; notranslate">
if (m == 1) {
//      h = h.replace(/\ssrc=/gi, &quot; mce_tsrc=&quot;);
//      h = h.replace(/\shref=/gi, &quot; mce_thref=&quot;);

        return h;
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.xykox.net/2010/09/10/tinymce-2-et-firefox-3-6-9-import-dimage/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Iconv et Ruby (le retour)</title>
		<link>http://blog.xykox.net/2010/09/03/iconv-et-ruby-le-retour/</link>
		<comments>http://blog.xykox.net/2010/09/03/iconv-et-ruby-le-retour/#comments</comments>
		<pubDate>Fri, 03 Sep 2010 16:16:15 +0000</pubDate>
		<dc:creator>jean-marc</dc:creator>
				<category><![CDATA[Non classé]]></category>

		<guid isPermaLink="false">http://blog.xykox.net/?p=19</guid>
		<description><![CDATA[Dans un précédent article, je vous parlais de ma découverte sur les problèmes avec iconv influencé par les variables d&#8217;environnements. En fait avec Ruby (1.8.6) ça se corse, car Ruby est aussi buggé. Alors on recommence les explications. L&#8217;influence de &#8230; <a href="http://blog.xykox.net/2010/09/03/iconv-et-ruby-le-retour/">Continuer la lecture <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Dans un <a title="Iconv et résultats variables" href="http://blog.xykox.net/2009/09/09/iconv-et-resultats-variables/">précédent article</a>, je vous parlais de ma découverte sur les problèmes avec iconv influencé par les variables d&#8217;environnements.</p>
<p>En fait avec Ruby (1.8.6) ça se corse, car Ruby est aussi buggé.</p>
<p>Alors on recommence les explications.</p>
<p>L&#8217;influence de la variable d&#8217;environnement sur iconv :</p>
<pre class="brush: bash; title: ; notranslate">
$ echo éà | LANG=fr_FR.UTF-8 iconv -f UTF-8 -t ascii//translit
ea
$ echo éà | LANG=C iconv -f UTF-8 -t ascii//translit
??
</pre>
<h4>Maintenant avec Ruby et Rails, ça se corse &#8230;</h4>
<p>Dans un premier temps, on vérifie que tout est ok avec irb.</p>
<p>Avec irb, avec &#8216;C&#8217;</p>
<pre class="brush: bash; title: ; notranslate">
$ LANG=C irb
irb(main):001:0&gt; require 'iconv'
=&gt; true
irb(main):002:0&gt; Iconv.iconv('ASCII//TRANSLIT', 'UTF-8', 'éèà')
=&gt; [&quot;???&quot;]
irb(main):003:0&gt;
</pre>
<p>maintenant irb et fr_FR</p>
<pre class="brush: bash; title: ; notranslate">
$ LANG=fr_FR.UTF-8 irb
irb(main):001:0&gt; require 'iconv'
=&gt; true
irb(main):002:0&gt;  Iconv.iconv('ASCII//TRANSLIT', 'UTF-8', 'éèà')
=&gt; [&quot;eea&quot;]
irb(main):003:0&gt;
</pre>
<p>Ok cool tout va bien <img src='http://blog.xykox.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Maintenant le runner de Ruby On Rails</p>
<pre class="brush: bash; title: ; notranslate">
$ LANG=fr_FR.UTF-8 script/runner &quot;puts Iconv.iconv('ASCII//TRANSLIT', 'UTF-8', 'ééà').inspect; puts ENV['LANG'].inspect&quot;
[&quot;???&quot;]
&quot;fr_FR.UTF-8&quot;
</pre>
<p>Et là on s&#8217;arrache les cheveux &#8230; qu&#8217;on change ou pas dans config/environement.rb, le résultat est toujours le même</p>
<p>Et pour vérifier que le problème ne vient pas de Rails, mais vraiment de Ruby :</p>
<pre class="brush: bash; title: ; notranslate">$ ruby -e &quot;require 'iconv'; puts Iconv.iconv('ASCII//TRANSLIT', 'UTF-8', 'éèà').inspect; puts ENV['LANG'].inspect&quot;
[&quot;???&quot;]
&quot;fr_FR.UTF-8&quot;
</pre>
<p>Donc on cherche un peu sur le net et la réponse est sur <a href="http://www.ruby-forum.com/topic/70827#745486">ruby-forum</a>  : en gros un problème d&#8217;initialisation de la variable d&#8217;environnement LC_TYPE.</p>
<p>Youpi &#8230; En plus <a href="http://www.ruby-forum.com/topic/70827#823930">Nobuyoshi Nakada</a> nous explique comment faire son patch .. </p>
<p>Pour plus de simplicité et de pérennité, j&#8217;ai fait mon package. D&#8217;abord télécharger les sources de <a href="/wp-content/uploads/locale-bug.tgz">locale-bug</a>.</p>
<p>Ensuite en tant que root :</p>
<pre class="brush: bash; title: ; notranslate">
$ tar -xvzf locale-bug.tgz
$ cd locale-bug
$ ruby extconf.rb
$ make
$ make install
</pre>
<p>Et dans votre application Rails (config/environment.rb) :</p>
<pre class="brush: ruby; title: ; notranslate">
...
require 'locale_bug'
LocaleBug.ctype = 'fr_FR.UTF-8'
require 'iconv'
...
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.xykox.net/2010/09/03/iconv-et-ruby-le-retour/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Solimap</title>
		<link>http://blog.xykox.net/2009/09/09/solimap/</link>
		<comments>http://blog.xykox.net/2009/09/09/solimap/#comments</comments>
		<pubDate>Wed, 09 Sep 2009 18:44:30 +0000</pubDate>
		<dc:creator>jean-marc</dc:creator>
				<category><![CDATA[Non classé]]></category>

		<guid isPermaLink="false">http://blog.xykox.net/?p=57</guid>
		<description><![CDATA[Juste pour faire un peu de pub à un développeur RoR, et pour son bébé qui est joliment fait pour un principe aussi vieux que le Web : Solimap un site d’annonces diverses. Du mashable, du RubyOnRails mais ça on &#8230; <a href="http://blog.xykox.net/2009/09/09/solimap/">Continuer la lecture <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Juste pour faire un peu de pub à un développeur RoR, et pour son bébé qui est joliment fait pour un principe aussi vieux que le Web : <a href="http://solimap.com">Solimap un site d’annonces diverses</a>. Du mashable, du RubyOnRails mais ça on ne le voit pas, de la transparence, simple et propre.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.xykox.net/2009/09/09/solimap/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Iconv et résultats variables</title>
		<link>http://blog.xykox.net/2009/09/09/iconv-et-resultats-variables/</link>
		<comments>http://blog.xykox.net/2009/09/09/iconv-et-resultats-variables/#comments</comments>
		<pubDate>Wed, 09 Sep 2009 15:52:38 +0000</pubDate>
		<dc:creator>jean-marc</dc:creator>
				<category><![CDATA[Configuration]]></category>
		<category><![CDATA[Web Dev]]></category>
		<category><![CDATA[iconv]]></category>
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://blog.xykox.net/?p=5</guid>
		<description><![CDATA[Arrg, il faut lire les pages de manuel en entier … iconv et toutes les wrapper dérivés sont influencé par les variables d’environnement LANG, LC_ALL, LC_CTYPE, LC_MESSAGES. Par exemple : Et comme bien sûr iconv est très bien documenté, il &#8230; <a href="http://blog.xykox.net/2009/09/09/iconv-et-resultats-variables/">Continuer la lecture <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Arrg, il faut lire les pages de manuel en entier … iconv et toutes  les wrapper dérivés sont influencé par les variables d’environnement  LANG, LC_ALL, LC_CTYPE, LC_MESSAGES.</p>
<p>Par exemple :</p>
<pre class="brush: bash; title: ; notranslate">
$ echo éà | LANG=fr_FR.UTF-8 iconv -f UTF-8 -t ascii//translit
ea
$ echo éà | LANG=C iconv -f UTF-8 -t ascii//translit
??
</pre>
<p>Et comme bien sûr iconv est très bien documenté, il va sans dire que ça été facile de trouver cette bizzarie.</p>
<p>Donc comme on dit dans ces cas là, ce n’est pas un bug mais une fonctionnalité, à voir chez debian : ”<a href="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=376272">Libc6: //translit fails with cyrillic and others</a>”</p>
<p>Et bien sûr quand vous lancez votre application rails avec Webrick dans votre environnement où LANG=fr_FR.UTF-8</p>
<pre class="brush: bash; title: ; notranslate">
$ locale
LANG=fr_FR.UTF-8
LC_CTYPE=&quot;fr_FR.UTF-8&quot;
LC_NUMERIC=&quot;fr_FR.UTF-8&quot;
LC_TIME=&quot;fr_FR.UTF-8&quot;
LC_COLLATE=&quot;fr_FR.UTF-8&quot;
LC_MONETARY=&quot;fr_FR.UTF-8&quot;
LC_MESSAGES=&quot;fr_FR.UTF-8&quot;
LC_PAPER=&quot;fr_FR.UTF-8&quot;
LC_NAME=&quot;fr_FR.UTF-8&quot;
LC_ADDRESS=&quot;fr_FR.UTF-8&quot;
LC_TELEPHONE=&quot;fr_FR.UTF-8&quot;
LC_MEASUREMENT=&quot;fr_FR.UTF-8&quot;
LC_IDENTIFICATION=&quot;fr_FR.UTF-8&quot;
LC_ALL=

$ script/server
</pre>
<p>Et d’un autre en lançant via passenger et que LANG est initialisé à “C”, alors on perd son temps à chercher le problème dans rails ou passenger.<br />
RTFM !</p>
<p>J’aurais bien aimé utiliser iconv avec la locale fr_FR, mais comme j’utilise iconv pour mes permaliens (enregistré en BD ce qui n&#8217;est pas une bonne idée au passage) qui ont été généré avec sans locale (LANG=C), alors pour éviter les problèmes, je force l’appli à utiliser LANG=C dans mon config/envirronment.rb</p>
<pre class="brush: bash; title: ; notranslate">
...
ENV['LANG'] = 'C'
...
</pre>
<p>jusqu’au prochain problème …</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.xykox.net/2009/09/09/iconv-et-resultats-variables/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

