Blogs

Rails 3 vient de sortir. Je vous encourage à lire l'annonce de la sortie sur le blog officiel, Riding Rails si vous ne l'avez pas déjà fait. Pour les nouvelles applications, il n'y a pas de doutes à avoir : Rails 3 est la route à suivre. Mais pour les applications existantes qui utilisent actuellement Rails 2.3, qu'en est-il ? C'est ce que nous allons voir en quelques questions-réponses.

Ai-je intérêt à passer à Rails 3 ?

Oui, Rails 3 apporte de nombreuses améliorations, et à peu près n'importe quelle application va tirer parti de l'une ou l'autre de ces améliorations. Par exemple, la protection par défaut contre les attaques XSS est un grand pas en avant et va simplifier la vie des développeurs. Rails 3 est également plus performant et permet de remplacer plus facilement ActiveRecord par un autre ORM. Bref, les raisons ne manquent pas de passer à Rails 3.

Puis-je passer dès aujourd'hui à Rails 3 ?

Cela dépend des projets. Rails 3 a été bien testé au cours des derniers mois avec 4 versions beta et 2 release candidates, il n'y a pas de problème de ce coté là. Mais passer à Rails 3 ne se fait pas magiquement. Il faut prendre le temps de découvrir la nouvelle version et migrer son application. Cela prend un peu de temps (de quelques jours à quelques semaines, selon la taille de l'application). Il faut donc voir si l'intérêt de passer à Rails 3 est suffisant pour justifier de passer ce temps, puis planifier cette migration, si possible lors d'une période calme.

Et pour les gems/plugins ?

La plupart des gems courants ont des branches sur leur dépôt pour fonctionner avec Rails 3. Des versions stables de ce plugin sont sorties ou vont sortir dans les jours à venir. Vous pouvez vérifier sur le site RailsPlugin.org que les gems que vous utilisez sont compatibles avec Rails 3.

Que faire si une gem n'est pas compatible avec Rails 3 ?

Si la gem n'est plus maintenue, c'est peut être l'occasion de passer à une gem équivalente plus évoluée. Vous pouvez aussi décider de reprendre le projet à votre compte en contactant l'auteur initial.

Si la gem est maintenue mais n'est pas encore fonctionnelle avec Rails 3, vous pouvez aider son auteur de différentes façons :

  1. Ouvrir un ticket sur le bug tracker du projet
  2. Suivre les développements en cours, les tester et remonter les problèmes
  3. Participer au développement en proposant des patchs, voir en créant une branche de code Rails3 spécialement pour l'occasion.

Pour une gem critique, une possibilité peut être de sponsoriser le passage à Rails à son auteur ou à un expert Rails 3.

Je suis décidé à passer à Rails 3, comment je fais ?

La première chose est de migrer vers la version la plus récente de Rails 2.3. La version 2.3.9 va sortir (demain si tout va bien), et permettra de migrer en douceur vers Rails 3. Si vous utilisez des API dépréciées, vous serez prévenu dans les logs. Cela vous permet de préparer une partie du terrain avant le grand saut. Ensuite, vous pouvez utiliser le plugin Rails upgrade pour vous aider à migrer, en suivant les explications de Jeremy McAnally.

Je vous conseille également la lecture de The Rails 3 Upgrade handbook. Le temps gagné grâce à sa lecture remboursera largement les quelques dollars qu'il coûte. Pour ceux qui aiment les vidéos, les 3 Railscasts valent également d'être regardés : partie 1, partie 2 et partie 3.

J'ai un dernier conseil pour la route : utilisez une branche séparée dans votre dépôt git/svn pour faire la migration. Vous aurez probablement besoin d'aller voir plusieurs fois votre application avant la migration et les changements faits depuis si vous rencontrez un point de blocage.

Et pour apprendre Rails 3, quelles ressources sont à ma disposition ?

Certains ont été plus rapides que moi, je vais donc me contenter de donner deux liens :

Sachez également qu'un livre en français est en cours de rédaction et devrait sortir dans les semaines à venir.

Et pour les autres questions ?

Vous pouvez poser votre question en commentaire de ce billet ou sur http://questions.rubyfr.org/.

Ce week-end avait lieu la PyCONFR (organisée par l'AFPy à la Cité des Sciences et de l'Industrie de la Vilette à Paris). J'ai pour ma part assisté à deux présentations très intéressantes :

  • "Aiguille et botte de foin : scikit-learn et joblib pour explorer des données volumineuses" de Gael Varoquaux;
  • "Analyse statistique et classification automatique de texte avec nltk et scikit-learn" de Olivier Grisel.

Les deux présentations tournaient autour des concepts de classification de l'information, que ce soit du texte (sur lequel était plus orientée la seconde présentation), ou de données autres (photos par exemple). Quelques outils intéressant on été cités :

  • scikit-learn: extension pour numpy/scipy qui fournit des implémentations de références des principaux algorithmes d'apprentissage artificiel (pour faire de la classification et prédiction entre autres) ;
  • nltk: natural language toolkit, outils permettant de parser du texte en anglais (ou quelques autres langues parlées) afin d'en extraire la structure des phrases (là aussi classification...) ;
  • joblib: un outils permettant d'organiser des jobs en pipeline, pour ne pas avoir à recalculer certains calculs et organiser des exécutions en parallèle.

Du côté du node.JS KO, quelques projets intéressants ont vu le jour, en voici quelques uns :

AF n'a finalement pas participé à l'évènement faute de volontaires disponibles (il faut dire ques les horaires locales + la Pyconfr n'ont pas arrangé les choses).

Bonne rentrée, et bonne semaine,
Pierre

Bonsoir à tous,

Pour finir cette calme semaine de fin de mois d'Août, voici quelques lien en vrac :

Bon week-end,
Pierre

Today I am going through whereever we are using the twitter api just a last minute verification we are basic auth free (and btw this basically just a test that all is fine).

Long live oauth.

We have been chasing a bug for quite a long time that made our lives miserable, and our client, very unhappy: When submitting a large form, intermittently the post data is broken (basically only the the first parts of the submitted form data get to Rails). The bug is caused by an incorrect implementation of parsing multipart/form-data in Rack 1.0 and earlier. This is the commit that fixes the issue : http://github.com/rack/rack/commit/a9440bc752be9b3093669614c6b56bf78d592958 you can also look at the added test case to try and reproduce the error.

We are without doubt not the first ones to fall on this, but as finding the bug was very, very hard. I am posting this as a public service hoping someone down the line will have an easier time finding the cause... the solution is easy. Either upgrade Rack to at least 1.1 or patch lib/rack/utils.rb. Also updating Ruby on Rails to > 2.3.6 will solve this as it has a dependency on Rack 1.1

The symptoms can vary, and what makes this bug very very hard to find is that it needs a lot of parameters to manifest itself. You might get validation errors on you models, or missing required parameters at the controller level: or just some unexpected behavior (Not tested, but might result in corrupted uploads). Basically what happened is that when the body data of a post is longer then 16384 and a multipart boundary is found at precisely 16384 bytes... the parser will return with therefor only the first parts parsed. So first, you need to have a huge form, now imagine the form represents something in your database, and you change the data: you need your new data to make the boundary arrive at precisely the slicing point. Considering that each browser may have a different size of boundary, the same change to the same data will not reproduce the error between two different browsers. Also because this executes inside the Application Controller at Racks level, you will find that the app's logs are going to be of very little service. We had to go wireshark on this bug, and follow the post data through all the levels to find where it broke. And we got lucky: we found offending POST data while testing... So basically you might find yourself with an application where from time to time, in what seems to be a completely random way, you will find fields missing from the POST data in production... but reproducing this on test servers might prove very very hard.

Note: this bug is not Rails specific and will happen with any framework using Rack. So just to help people find this: Broken form data on Sinatra, ruby corrupted post, big form fails intermittently with rack. Uploading Files randomly fails Ruby on Rails. Missing Post Data Ruby. Ruby multipart bug. Rails multipart problem.

Rest-mongo is a javascript library for NodeJS and the browser. On the node's side it features an ORM in front of a Mongo DB. On the client's side, it features the same ORM but with a REST API backend. The server-side part can also expose the REST API needed by the client (but there is no notion of authorizations yet). It works by specifying a JS schema of your data (schema that can be shared by both your client and server code). Here is an example of schema:

  1. var schema = {
  2.   "Person": {
  3.     resource: "/people",
  4.     schema: {
  5.       id: "Person",
  6.       description: "someone, blablabla",
  7.       type: "object",
  8.  
  9.       properties: {
  10.         firstname: {type: "string"},
  11.         friends: {type: "array", items: {"$ref": "Person"}},
  12.         mother: {"$ref": "Person"}
  13.       }
  14.     }
  15.   }
  16. };

Here we have described a Person that has the following properties:

  • firstname, string;
  • friends, list of references to other persons;
  • mother: reference to another Person.

The "resource" property of the Person object is not mandatory, but is needed if you want to expose/use the REST API.

Once we have a schema describing our data, we need to get the "R" object (describing a unit of work). Get a new R every time you need to get a new context to work in (at every client request for example).

  1. var rest_mongo = require("rest-mongo");
  2. var RFactory = rest_mongo.getRFactory(schema, "db_name");
  3. var R = RFactory();

Then we can start hacking around:

  1.  // Create and save an object into the DB:
  2.  var lilly = new R.Person({firstname: "Lilly"});
  3.  lilly.save(function() {
  4.    sys.puts("Lilly saved in DB with id " + lilly.id());
  5.  });
  6.  
  7.  // Get one or more objects from DB:
  8.  R.Person.get({
  9.    ids: lilly.id()
  10.  }, function(lilly2){
  11.   // lilly and lilly2 are the same
  12.  });
  13.  
  14.  // Search in DB:
  15.  R.Person.index({
  16.    query: {firstname: "Lilly"}
  17.  }, function(data){
  18.    var lilly = data[0];
  19.  });
  20.  
  21.  // Delete an object:
  22.  lilly.delete_(function(){
  23.    sys.puts('Lilly deleted from DB!');
  24.  }, function(err) { // the 2nd callback is a fallback (not mandatory)
  25.    sys.puts('You can not delete Lily!');
  26.  });
  27.  
  28.  // Usage of references:
  29.  var harry = new R.Person({firstname: "Harry", mother: lilly});
  30.  harry.save(function() {
  31.    sys.puts('Only the id of Lilly has been saved in harry.mother in DB.');
  32.  });
  33.  
  34.  // Update more than one field in once:
  35.  R.Person.update({
  36.    ids: [lilly.id(), harry.id()], 
  37.    data: {firstname: 'anonymous'}
  38.  }, function() {
  39.    sys.puts("Voldemort cannot find them anymore...");
  40.  });
  41.  
  42.  // Save more than one object in once:
  43.  var p1 = new R.Person({firstname: 'Hermione'});
  44.  var p2 = new R.Person({firstname: 'Ron'});
  45.  R.save([p1, p2], function() {
  46.    console.log('Now Harry has friends.')
  47.  }, function(error) {
  48.    console.log('Harry has no friends, because of ', error);
  49.  });
  50.  

Of course the project is lacking a lot of features that could be interesting to have, but it's well documented and tested, so don't hesitate to hack on it. It has been tested and works fine on node v0.1.100, we should soon update it for node 0.2.0.

It uses node-mongodb-native to connect to mongoDB and nodetk for orchestration, tests and other miscellaneous tools. It has been used to build Geeks, a fun events based {office, place, ...} map to locate people (and eventually do a lot of other things).

Have fun and don't hesitate to comment,
Pierre

Rest-mongo on GitHub: http://github.com/AF83/rest-mongo.

Node.js est un environnement Javascript pour faire tourner applications réseau scalable. Sa particularité, qui en fait aussi sa force, est de reprendre le modèle événementiel bien connu des développeurs Javascript et de l'utiliser pour des applications coté serveur.

Chez af83, nous nous intéressons à Node.js depuis un bout de temps, mais il était assez difficile de développer sérieusement des applications avec, les versions mineures s'enchaînant et cassant l'API.

Toutefois, ceci devrait devenir de l'histoire ancienne : Ryan Dahl vient d'annoncer Node.js v0.2.0 et il va s'employer à conserver une API stable pour les versions 0.2.x. Ceci devrait permettre aux bibliothèques et frameworks autour de Node.js de pouvoir se développer plus sereinement et de construire plus facilement des applications Node.js sans avoir à se compliquer la vie pour trouver une version de Node.js qui fonctionne avec toutes les bibliothèques que l'on souhaite utiliser.

For the Whyday, I've hacked two ZSH scripts for completion of RVM and bundler 1.0. You can find them on my dotfile repository on github: http://github.com/nono/dotfiles/blob/master/zsh/Completion/_rvm and http://github.com/nono/dotfiles/blob/master/zsh/Completion/_bundler.

To install them, you can put these 2 files in $HOME/.zsh/Completion (create this directory if it doesn't exist), and add it to fpath by adding this line to your .zshrc:

fpath=(~/.zsh/Completion $fpath)

A quick example of completion:

% bundle install --[TAB][TAB]
--binstubs    -- generate bin stubs for bundled gems to ./bin
--deployment  -- install using defaults tuned for deployment environments
--frozen      -- do not allow the Gemfile.lock to be updated after this install
--gemfile     -- use the specified gemfile instead of Gemfile
--local       -- do not attempt to connect to rubygems.org
--no-color    -- disable colorization in output
--path        -- specify a different path than the system default
--quiet       -- only output warnings and errors
--system      -- install to the system location
--without     -- exclude gems that are part of the specified named group

Bonjour à tous,

Voici quelques liens de veille :

Bonne fin de semaine,
Pierre

Bonsoir,

Pour bien finir le mois de Juillet, une poignée de liens de veille :

Bon WE,
Pierre