Shiny happy people coding

Codons avec le sourire

0 Downtime avec Unicorn

| Comments

J’ai eu la chance de participer au premier rendez vous BBL Paris. Dans le cadre de cette rencontre, nous avons parlé de nos processus de déploiement. Je vais essayer de faire quelques billets sur mes processus de déploiement.

Le Server web

Pour déployer une application ruby, il nous faut un serveur web. Il en existe beaucoup dans l’écosystème ruby. Passenger, Thin, Unicorn, Puma sont les plus connus. J’utilise personnelement unicorn depuis plusieurs années. Mon choix a surtout été fait suite à la possbilité d’avoir un 0 Downtime. J’utilisais précédement thin et la mise en place d’un 0 downtime est assez compliqué. Pour Unicorn, tout est fait en interne. C’est une fonctionnalité de base.

Comment réaliser ce 0 downtime ?

Pour expliquer comment ceci est possible, il faut comprendre l’architecture de Unicorn. Unicorn a un système maître / workers. Au démarrage de unicorn, un processus maitre se lance et lance une série de processus par fork(2) suivant la configuration. Tous ces processus seront ceux qui exécuteront réelement votre application. Le processus maitre ne sert qu’à gérer le dispatching entre les différents workers.

L’avantage de cette architecture est que vous n’avez pas besoin de load-balancing devant votre unicorn. C’est unicorn lui-même qui gére le système.

Mais ce qui est très pratique est que le processus maitre comprend très bien les signaux UNIX. Les signaux UNIX sont hélas très souvent sous-utilisé alors qu’ils sont très puissant.

Le signal le plus utile pour notre 0 downtime est le USR2. D’après la documentation, “relance l’executable binaire. Un QUIT doit être envoyé au process original une fois que l’enfant a été constaté comme UP et lancé”. En résumé, quand le processus maitre recoit le SIGNAUX USR2, il relance un nouveau process maitre. Par contre, la documentation explique bien qu’il faut penser à lancer un SIGNAUX QUIT au process initial pour qu’il s’arrête réelement.

Pour réaliser ce dernier point, il faut donc penser à configurer correctement unicorn pour qu’il fasse ce QUIT. Voici donc la configuration que j’utilise pour ça.

1
2
3
4
5
6
7
8
9
10
11
12
before_fork do |server, worker|

  old_pid = "pids/unicorn.pid.oldbin"
  if File.exists?(old_pid) && server.pid != old_pid
    begin
      Process.kill("QUIT", File.read(old_pid).to_i)
    rescue Errno::ENOENT, Errno::ESRCH
      # someone else did our job for us
    end
  end

end

le before_fork se lance une fois que le processus maitre est UP et qu’il va commencer a créer un fork pour avoir un travailleur.

Le Signal QUI lancé durant le before_fork arrêtera les processus Unicorn une fois qu’il a fini de traiter toutes les requêtes en cours. C’est ce méchanisme qui nous permet le 0 downtime.

Le problème du Gemfile

Toutes les personnes qui n’utilise pas ce méchanisme, ne le font pas suite à un problème de configuration avec Bundler. Une documentation compléte existe à ce sujet.

En gros, la technique est simplement de penser à définir le PATH du Gemfile directement par la variable d’environement BUNDLE_GEMFILE.

Soit lors du démarrage du process.

1
BUNDLE_GEMFILE=./Gemfile unicorn -c config/unicorn.rb

Soit directement dans le fichier de configuration de unicorn

1
2
3
before_exec do |server|
  ENV["BUNDLE_GEMFILE"] = "./Gemfile"
end

Une fois que vous avez configuré correctement votre Gemfile, vous n’avez plus de problèmes.

Un moyen simple de détection de problème lors du reload, est de vérifier qu’un nouveau process unicor c’est bien lancé. Si ce nouveau process échoue, il n’enverra pas le signal QUIT. Le premier process reste donc vivant et UP. Cela évite entre autre d’avoir une indisponibilité à ce moment là. On peut vérifier cela avec un simple ps :

1
ps o "start command" | grep unicorn

Au pire, il suffit cette fois ci de faire un restart du processus.

Autre problèmes possible

Pour les malchanceux comme moi qui ont des applications qui ne sont pas encore en rails > 3.0, attention il faut penser à utiliser l’executable unicorn_rails.

J’espére vous avoir faire découvrir mes petits astuces sur Unicorn et que cela vous sera utile.

Release de public folder

| Comments

Depuis maintenant 1 semaine, je suis à la recherche d’un nouvel emploi. Durant ma recherche d’emploi, on m’a fait une demande d’exercice en Ruby. Étant un convaincu de l’open source et étant globalement fier de ce que je peux produire, j’ai décidé de le sortir en open source.

Voici donc Public Folder

Ce projet est extrêment simple, il s’agit d’une interface de gestion de répertoires. À partir de la racine, on peut ainsi naviguer à travers une arborescence que l’on peut créer soit même. On peut donc créer des répertoires et uploader des fichiers directement dans l’application.

Le stockage des fichiers se fait directement sur disque dans la même arborescence que celle définie dans l’application. Elle est juste comme git, si vous créez un dossier dans l’application et qu’il ne contient aucun fichier, le dossier ne sera pas créé sur le disque.

Au niveau de la navigation, l’url correspond à l’architecture du dossier et on peut trier chaque liste par date/type/poids ou noms.

Pour réaliser cette application, la stack est full Rails, soit ActionPack et ActiveRecord. J’ai juste utilisé decent_exposure, simple_form et draper comme gems. Je ne peux plus du tout me passer d’eux tellement ils sont devenu essentiel pour moi.

Ce projet est complétement testé. J’ai une couverture de test de 99% selon Coveralls. Il a une note de 4 sur CodeClimate. Vous pouvez le voir aussi sur Travis.

Je ne compte pas continuer le développement de cette application. Je n’en ai strictement aucun besoin. Par contre, je la laisse à la postérité et aux lecteurs de code en tout genre.

pourquoi j’ai arrêté decent_exposure

| Comments

A la sortie de decent_exposure, j’ai été très enthousiaste. J’utilisais avant inherited_ressources, mais je commençais à découvrir les problèmes de inherited_resources. La personnalisation de son controller peut vite devenir compliqué et peux lisible si on sort du cadre d’un controller qui soit plus qu’un CRUD simple. On finissait par avoir un code moyennement DRY et les test étaient loin d’être évident car impossible coté controller ( limitation indiqué dans le README lui-même ).

Le grand avantage que j’ai vu dans decent_exposure est la facilité d’accès des variables dans les vues. Plus besoin de faire appel à des instances. On appele simplement la méthode. Si celui-ci n’était pas instancié alors decent_exposure le faisait pour nous. On obtenait ainsi un système beaucoup plus souple qui ne chargeait les objets qu’au moment ou il était nécessaire. Un eager loading intégré permettait d’éviter de rechercher en base plusieurs fois le même objet. On pouvait aussi réutiliser plusieurs fois la même vue. plus besoin de faire des assignations dans certaine action pour être sur que l’objet existe. Il suffit juste d’exposer l’objet. Après on l’utilise ou pas. De même l’utilisation des partials devient plus aisé car, on peux surcharger facilement des variables par l’usage des locals. J’y ai vu beaucoup d’intérêts.

Mais finalement cet intérêt n’existe que par l’usage de la méthode de class d’un controller helper_method. Si on crée soit même sa propre méthode avec son eager loading decent_exposure devient inutile.

decent_exposure a été pour moi un révélateur de l’utilité de la méthode helper_method. Mais à l’usage, je trouve qu’il fait finalement trop de chose caché si on utilise la méthode d’appel expose sans bloc. Je me suis ainsi retrouvé à faire des update_attributes 2 fois sur mon objet. Un dans le decent_exposure l’autre dans mon action. Forcement ça posait quelques soucis. Quand on sait que cela peut arriver, pas de soucis. Mais c’est toujours embêtant de perdre quelques heures à débugger le problème quand on le voit. Sans compter les fois ou on ne le voit pas.

Une des limitations de decent_exposure selon moi est l’override de cette méthode. Parfois pour éviter les if infini dans cette méthode il est plus judicieux de définir directement la valeur de retour de cette méthode dans sa méthode d’action. Cela permet de savoir exactement ce que retourne cette méthode, mais aussi d’éviter les conflits dans d’autre action.

Pour réalisé cela ma méthode stocke en mémoisation la variable d’instance égale au nom de la méthode. Ainsi ma méthode ressemble à ceci :

1
2
3
4
def post
  @post ||= Post.find(params[:id])
end
helper_method :post

Si je souhaite donc avoir un nouveau Post retourné par cette méthode j’ai juste à faire :

1
2
3
def new
  @post = Post.new
end

Je surcharge le retour de la méthode post par la valeur Post.new. Pour faire cela avec decent_exposure il faut surchargé la variable @_resource[:post]. Mais rien ne m’assure que ce nom de variable d’instance soit conservé dans les futurs version de decent_exposure. Une solution serait peut-être de créer une méthode post=() lors de l’exposition d’un post, mais cela devient peut-être moins pratique.

Voilà donc les raisons de mon arrêt d’utilisation de decent_exposure. Je peux très facilement émuler le comportement de decent_exposure et tout ça sans aucune dépendance externe.

tester ses vues rabl

| Comments

Personnelement, quand je fais des API, j’utilise le gem Rabl. Je trouve ce gems vraiment génial. Avant son utilisation, je faisais mes API json avec la méthode #to_json. Mais pour ceux qui l’on utilisé, vous savez que c’est un enfer à maintenir. Surtout si vous avez plusieurs type de représentation de votre objet à différent endroit.

Rabl la simplicité d’expression

Pour gérer ses vues en JSON ou XML, les gems classique sont JBuilder et XmlBuilder. Deux gems réalisées par DHH. Mais, personnelement, je les trouves assez verbeuses comme vues. A contrario, Rabl a une syntaxe trés simplifiée. On peux ausi avoir un système de partial qui permet une réutilisation compléte. Petit bonus par rapport à JBuilder/XmlBuilder est qu’il utilise la même vue pour générer du XML ou du JSON. Donc pas besoin de faire plusieurs vues en fonction du format de sortie.

Voici un example de vue Rabl :

1
2
3
4
5
object @post
attribute :content
child(:author) do
  attribute :firstname, :lastname
end

Tester sa vue Rabl

Pour tester le résultat de cette vue Rabl, deux possibilités s’offre à nous. Un test de la génération de la vue par un test d’intégration couplé avec le test du controller, soit un test de la vue. Finalement tester une vue Rabl c’est ni plus ni moins que tester un retour de la méthode #to_json. Donc si nous testons notre vue directement à partir des données passées, c’est plus rapide et plus unitaire.

Depuis la version 0.6.0 de Rabl, une méthode permet de générer la vue directement. C’est cela que nous allons utiliser pour faire notre test de vue.

Voici donc un test de notre vue ( défini dans spec/views/posts/show_rabl_spec.rb )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
require 'spec_helper'

describe "blogs/show.rabl" do

    let(:auhor) { Author.new(:firstname => 'Cyril', :lastname => 'Mougel') }
    let(:blog) { Blog.new(:content => 'hello', :author => author) }
    let(:valid_json) {
      {
        :content => blog.content,
        :author => {
          :firstname => author.firstname,
          :lastname => author.lastname
        }
      }.to_json
    }

    let(:render) {
      Rabl.render(
        blog,
        'blog/show',
        :view_path => 'app/views'
      )
    }

    it 'should render valid_json' do
      render.should eql(valid_json)
    end

end

On obtient ainsi un test unitaire vraiment simple et une validation compléte du json obtenu. Le test est vraiment très rapide et n’est pas pollué par le test du controller.

J’ai par contre découvert des limitations à ce test car, on ne peux passer à la méthode #render que les objects définis par object ou collection. Si on veux tester une vue rabl qui utilise plusieurs variables, la tâche devient très hardu. J’ai donc commencé à proposer un Pull Request pour passer directement des variables dans sa vue Rabl, de la même méthode que les partials avec l’options :locals. Vous pouvez la suivre sur github

English translation

vundle ou le bundler de vim

| Comments

Personnellement, j’utilise vim comme éditeur de texte depuis mon école. J’ai toujours apprécié vim et je ne compte toujours pas changer d’éditeur.

Mon évolution de la gestions des plugins vim.

Vim a une très grande quantité de plugins disponibles et il est très rapidement indispensable d’en utiliser plusieurs. La gestion des plugins est donc très importante. Au fil des années, j’ai changé de technique en fonction des possibilités apportées par vim ou par les développeurs.

Gestion manuelle

Au début, je gérais manuellement mes plugins en les ajoutant dans les dossiers correspondant. Je versionnais mon dossier .vim et .vimrc et je pouvais le faire évoluer globalement. Le soucis de cette technique est qu’il est pas forcement évident de gérer les mises à jour des plugins et leur installation n’est pas forcement simple car il faut mettre plusieurs fichiers à plusieurs endroits.

L’arrivée des vimballs

Dans une évolution de vim, il y a eu la possibilité de gérer des vimballs. L’avantage de cette technique est qu’on avait moins de problème lors de l’installation et on pouvait gérer un peu plus facilement les mises à jour car on savait rapidement quelle version on utilisait. Mais la encore il fallait allez régulièrement sur vimscript.org pour voir si nos plugins avaient changé de version. Chose que finalement on faisait très peu au final.

Gestion par git-submodule

Avec l’arrivée de github, les choses ont pu changer. Les plugins vim ont commencé à avoir un dépôt centralisé, on pouvait suivre directement l’évolution des scripts. Même vimscript a converti tous les plugins qu’il hébergeait en repository git. Maintenant on peux gérer tous ses plugins en faisant des mises à jour de repository git. J’ai ainsi commencé a gérer des submodule et des liens symboliques vers ces submodules. La mise à jour était automatique, mais l’installation devenait encore plus compliqué qu’avant.

Janus, la distribution vim

C’est alors que Yehuda Katz et Carl Lerche ont commencé à créer janus. Ce projet se veut comme une distribution de gestion de plugins vim. Il contient un jeu de tâche rake qui permette de mettre à jour facilement ses plugins. Un .vimrc est aussi fourni pour utiliser les plugins par défaut et ajouter une configuration minimal pratique. Ce projet est vraiment génial pour commencer à pratiquer vim. On peux ainsi avoir un jeu de plugins pratique et intéressant. Par contre, la gestion des versions de janus avec ses propres usage peux vite devenir compliquée. En gros c’est bien si on ne veut jamais modifier sa conf vim.

Pathogen, le premier plugin vim de gestions de ses plugins

Très peu de temps après Tim Pope ( très prolifique développeur de plugins vim ) a sorti Pathogen. Ce plugin permet de gérer directement la gestion de ses plugins dans son vimrc. J’avoue ne pas avoir trop regardé comment fonctionne ce plugin. On m’en a toute fois dit du bien. Il y a eu pas mal de projet pour que janus utilise pathogen typiquement.

Vundle, le bundler de vim.

Mais c’est là qu’on m’a parlé du plugin qui me semble le meilleur actuellement concernant la gestion de ses plugins vim, Vundle. Comme pathogen, la gestion des plugins est faite directement dans son vimrc. Son usage y est très simplifié et pratique. Si vous connaissez Bundler alors vous comprendrez facilement sont usage car il en est très inspirés.

Utilisation de Vundle

Installation de Vundle

Pour installer vundle, un simple clone du repository du projet et 2 lignes dans votre .vimrc suffisent.

1
git clone https://github.com/gmarik/vundle.git ~/.vim/bundle/vundle
1
2
set rtp+=~/.vim/bundle/vundle/
call vundle#rc()

Configuration de ses plugins

Pour utiliser vundle une fois installé. C’est extrêmement simple. il suffit d’utiliser la commande Bundle et le chemin de votre plugin. Ainsi pour installer le plugin vim-rails il suffit juste de faire :

1
Bundle 'tpope/vim-rails.git'

Installation de ses plugins

Ensuite, une fois votre vim lancé deux commandes vous suffisent. BundleInstall qui permet d’installer tous les plugins que vous avez définis et BundleInstall! qui permet de les mettre à jour.

Désormais ils ne vous reste plus qu’à trouver les plugins que vous souhaitez et les utiliser.

Mon vimrc

Si vous souhaitez découvrir mon usage de vim, mon vimrc est ainsi disponible sur github. Grâce à Vundle rien de plus simple que de le lire et découvrir rapidement les plugins vim que j’utilise.

English Translation

dante pour mettre du daemon dans son code

| Comments

J’ai dernièrement eu besoin de convertir un petit script ruby en daemon.

J’utilise dans mes déploiements monitrc pour le monitoring de mes scripts. Monit check un pidfile pour voir si le processus est actif ou pas.

J’ai donc cherché en Ruby quel était la meilleure solution pour que mon script soit un daemon et puisse générer lui-même son pidfile.

Le projet le plus connu est daemons. J’ai déjà essayé de l’utiliser, mais je n’en ai jamais été un grand convaincu. Je l’ai toujours trouvé compliqué. Il ne gére pas la génération de pidfile. Il faut donc pratiquement tout gérer soit même.

Le deuxième projet le plus connu est une sur-couche de daemons c’est daemon-kit. J’avais déjà tenté de l’utiliser, mais je le trouve vraiment trop rigide pour un simple script. C’est selon moi plus une massue qu’autre chose pour créer un daemon.

C’est alors que je me suis rappelé avoir entendu parlé d’un nouveau gem pour créer des daemons. J’ai cherché et j’ai ainsi pu découvrir dante. Ce projet est exactement ce que je cherchais. Il est simple et fait le boulot de créer un daemon.

Par défaut, il supporte quelques arguments à passer en ligne de commande. Ces arguments font l’essentiel du travail d’un daemon.

Voici une liste des arguments par défaut disponible.

1
2
3
4
5
6
7
8
9
10
11
-p, --port PORT           Specify port
                          (default: )
-P, --pid FILE            save PID in FILE when using -d option.
                          (default: /var/run/scheduler.pid)
-d, --daemon              Daemonize mode
-l, --log FILE            Logfile for output
-k, --kill [PORT]         Kill specified running daemons - leave
blank to kill all.
-u, --user USER           User to run as
-G, --group GROUP         Group to run as
-?, --help                Display this usage information.

On peux ainsi définir, le PID, le fichier de log, l’utilisateur et le group lançant le daemon ( si lancé en root ). Seul petit argument qui ne me semble pas essentiel, c’est l’argument du port. Mais l’usage initial de dante est de lancé des applications rack. Voila pourquoi on retrouve cet argument.

Une de ses autre fonctionnalités intéressantes est tout simplement le fait que l’on peux ajouter des options. Il peux donc aussi servir de gestion d’option pour son application.

Pour l’utiliser rien de plus simple. Il suffit de mettre votre script dans un block Dante.run

1
2
3
Dante.run('myapp') do |opts|
  myapp.run
end

Je suis vraiment impressionné par ce gem qui est issu de la société gomiso. Merci à elle de nous permettre d’avoir d’aussi bon gem.

English Translation

moped le nouveau driver mongodb pour ruby

| Comments

Depuis décembre 2011, Bernerd Schaefer a commencé a créer un driver MongoDB pour ruby. Ce nouveau driver MongoDB n’a pas été crée par 10Gen (créateur de MongoDB) contrairement au gem mongo-ruby-driver.

Le but de ce gem

Ce gem a été crée suite aux frustrations de l’équipe de développement de Mongoid qui a fait plusieurs fois des propositions de changement de design du driver officiel. Tous changement de design du driver a été refusé.

Thread-safe

Un des buts de ce gem est de permettre d’avoir un gem qui est le plus possible thread-safe. Le driver officiel mongoDB est parfois considéré comme non thread-safe notament par Mike Perham. C’est un vrai problème alors que la communauté ruby commence enfin à redécouvrir les threads. Cet état empêche par exemple l’usage de sidekiq avec MongoDB.

Suppression de l’extension

Avec le driver MongoDB officiel, il est très fortement conseillé d’installer le gem bson_ext sans celui-ci les performances sont beaucoup moins bonnes. Par contre cette extension étant écrite en C, elle est incompatible avec JRuby. Il a fallu créer une version JRuby du gem bson. Ça rend la maintenabilité plus complexe.

Dans le cas de moped, aucune extension C n’est à prévoir. Il est naturellement plus performant. Il arriverait même à être plus performant que l’extension C selon les benchmarks réalisés pour le projet.

Seul ombre au tableau, la génération d’un ObjectId est plus lente avec moped qu’avec le gem officiel bson selon un thread de la mailing-list de Mongoid. Mais cela pourra être améliorer par la suite, je n’en doute pas.

Une API plus simple

L’API de moped est vraiment plus belle que celle du gem mongo. Ce changement est bien sûr subjectif. Elle est beaucoup plus orienté ruby. Elle permet aussi la combinaison de recherche/mise à jour.

Meilleure gestion du replicat Set

Une des fonctionnalités principale de MongoDB est la gestion du replicatSet. Avec Moped, cette gestion devient vraiment plus souple et surtout ne lève plus d’exception la première fois que le node maître est down. Cette fois ci le basculement se fait automatiquement.

Plus besoin de passer la liste de vos nodes en configuration. Moped utilise directement les mécanismes de MongoDB pour découvrir les nouveaux nodes et ainsi les utiliser.

Les limitations

Par contre, moped a certaine limitation.

Ruby 1.9 uniquement

Moped n’est pas compatible avec Ruby < 1.9. Le choix de l’implémentation a été fait de ne pas être compatible avec les plus anciennes version de ruby.

Personnellement, je suis d’accord avec ce choix, car l’usage de ruby 1.8 doit disparaitre.

Pas de support de GridFS

GridFS n’est pas supporté nativement dans moped. Ce choix a été fait pour limiter le core du gem. Bien sûr rien n’empêche de créer une extension de moped gérant GridFS.

Intégration dans Mongoid 3

Mongoid 3.x utilisera désormais moped à la place du driver mongodb de 10Gen. Si vous souhaitez donc commencer un peu à l’utiliser essayer cette nouvelle version majeur de Mongoid.

Attention, Mongoid 3 n’est actuellement pas release. Si vous souhaitez l’utiliser il faudra utiliser la branche master de Mongoid. Le dévelopment y est toujours actif.

1
gem 'mongoid', :git => 'git://github.com/mongoid/mongoid'

English Translation

Quiet Assets le gem qui limite les logs

| Comments

Voici une semaine, j’ai découvert un gem vraiment pratique. quiet_assets.

Ce gems ne fait pas grand chose, mais a de grand avantage quand on développe une application Rails (> 3.1) avec des assets en utilisant la technologie ‘asset_pipeline’.

Si c’est votre cas, vous vous êtes déjà rendu compte que chaques requêtes faites à votre application pour obtenir vos assets est logués dans votre fichier de log ( development.log en environement de dévelopment ). Des requêtes comme celle-ci :

1
2
Started GET "/assets/application.js?body=1" for 127.0.0.1 at 2012-02-13 13:24:04 +0400
Served asset /application.js - 304 Not Modified (8ms)

On se retrouve ainsi à devoir remonter dans son fichier de logs pour obtenir les logs qui nous interresse vraiment ( les log de la requête courante ). Notre fichier de log est vraiment pollué par ces assets si vous en avez comme moi beaucoup.

C’est là que quiet_assets devient vraiment interressant et pratique. Vous ajoutez ce gem dans votre Gemfile au niveau du groupe ‘development’ et tous vos logs d’assets disparaissent. Ils ne sont tous simplement plus logguées dans votre fichier de log. On retrouve ainsi un fichier de log rapide a consulter et moins pollué par des informations inutiles.

Comme quoi de tout petits gems peuvent nous rendre de grand service.

Edit du 27 Avril 2012

On pourrait se dire que cela pourrait être directement integré à Rails. Hélas cela à été fait en partie, mais pas complétement.

Depuis la version 3.2.x et l’issue 2639 nous pouvons configurer le logger de Sprockets. Mais il n’est pas seul à afficher les informations. Actionpack log toujours les requêtes faites pour obtenir ces assets. Vous ne pourrez donc pas avoir un fichier de log complétement épuré.

English translation

Récupération de ses fichiers sur basecamp

| Comments

Au niveau de mon travail actuel chez Be My Boat, nous sommes actuellement en train de migrer de Basecamp vers Trello.

Pour éviter de perdre toutes les informations qui ont été mis dans basecamp, nous avons réalisé un import complet. Par contre, l’import ne comprend pas les fichiers qui ont pu être ajouté dans basecamp.

Pour ne pas perdre ces fichiers qui font parti du patrimoine de l’entreprise, j’ai créé un petit script pour télécharger tous ces fichiers.

Je vous le partage si vous en avez besoin un jour.

Dans ce script j’utilise Faraday pour faire le requêtage avec l’API et aussi télécharger les fichiers. Je suis personnellement un grand fan de Faraday. C’est selon moi la meilleure librairie de requêtage HTTP actuelle du monde Ruby. Utilisez la dès que vous avez besoin de faire du requêtage HTTP.

Localize avec mongoid

| Comments

Depuis la version 2.4.0 de Mongoid, une nouvelle fonctionnalité à été ajoutée très discrétement. C’est tout simplement la gestion native des traductions en base.

La documentation compléte de cette fonctionnalité est sur le site de mongoid.

Grâce à cette fonctionnalité, on peut définir tout simplement qu’un champs de Mongoid est localizable. La gestion de la locale est faite de manière très intelligente et surtout en complète coordination avec MongoDB.

Contrairement à une gestion de traduction dans une Base de donnée relationnelle, qui créé une table de liaison, Mongoid stocke un hash avec la locale comme clé et la traduction comme valeur.

Mongoid n’a plus qu’à faire la glue entre le système pour que les accès en lecture/écriture en fonction de la locale et la recherche