Rails : bien préparer sa BDD pour stocker des Emoji
Ddans cet article début d’approche sur la problématique pour stocker des "Emoji" en BDD
Effectivement on pense que cela ne sert à rien de les utiliser mais le problème avec ces icônes est qu’ils sont disponibles nativement sur la plupart des claviers mobiles désormais, et donc … peuvent se retrouver dans le moteur de n’importe quel formulaire de votre site. Si vous ne gérez pas ce cas particulier, cela peut engendrer des erreurs.
La fausse piste “serialize”
Certains optent pour la solution un peu brute et pas forcément de bonne augure de spécifier dans un model que tel champ est à “serializer” (je suis moi aussi un peu tombé dedans ^^)
class MonModel < ActiveRecord::Base
serialize :mon_champ
end
Alors effectivement ça “marche” mais allez jeter un oeil en BDD et cela vous enchantera moins (d’autant plus qu’il sera difficile de requêter sur ce genre de données avec des conditions par exemple).
Serialize sert avant tout à nous aider à sauvegarder des données en tant qu’objet (au passage, en YAML). Passons donc cette alternative.
Un problème d’encodage avant tout
Le problème avec les encodages classiques en utf8 est que ce dernier utilise au maximum 3 octets par caractère. Les Emoji en nécessitent 4 ! Depuis la version MySQL 5.5.3, l’encodage utf8mb4 permet de manipuler tous les caractères unicodes de 4 octets (comprenant donc nos fameux emojis).
L’avantage est qu’il suffit de configurer notre BDD pour lui dire d’utiliser cet encodage précis. Attention toutefois, il vous faut MySQL >= 5.5.3.
Création et configuration de notre projet Rails
Nous allons dans un premier temps créer un projet Rails et le configurer pour mettre par défaut ce nouvel encodage (nous reviendrons dans un autre article sur la manière de procéder pour mettre à jour des colonnes sans perte de données sur un projet existant).
# Necessite rails >= 4 et surtout MySQL >= 5.5.3
rails new mon_projet -d mysql
# On modifie notre database.yml
# ...
adapter: mysql2
encoding: utf8mb4
charset: utf8mb4
collation: utf8mb4_unicode_ci
# ...
# On créer un fichier dans config/initializers/utf8mb4
require 'active_record/connection_adapters/abstract_mysql_adapter'
module ActiveRecord
module ConnectionAdapters
class AbstractMysqlAdapter
NATIVE_DATABASE_TYPES[:string] = { :name => "varchar", :limit => 191 }
end
end
end
Comme vous pouvez le constater, on précise ici une limite de 191 pour nos types “varchar”. Habituellement on est sur du 255. En utf8 la taille maximum de l’index est de 767 octets, donc on a 767 / 3 octets par caractère = 255 caractères max pour l’utf8 habituel, et pour l’utf8mb4 on obtient 767 / 4 octets par caractère = 191 caractères max.
# On créer notre BDD
rails db:create
rails db:migrate
# On créer un objet de test
rails generate scaffold articles titre contenu:text
Lancez votre projet et rendez-vous sur la page de création d’un article, placez-y un titre et du texte avec un emoji dans chaque champ. Vous n’aurez pas de problème lors de la sauvegarde en BDD
Sources : Documentation MySQL utf8mb4
Originally published at Sois-net.