Project Oxygen & Ideo-LabIDEO LAB Dashboard 2026

💎 Ruby – Le Guide Ultime

Deep Dive : Philosophie (Matz), Blocs (yield), POO (Mixins), Gems (Bundler) & Ruby on Rails.

1.1 Facile

1. Philosophie & Syntaxe

"Bonheur du développeur" (Matz). puts, @var. Fin de ligne (; optionnel).

Matz Syntaxe
1.2 Facile

2. Contrôle (if/unless/loops)

if/elsif/end. La magie de unless. while/until. Itérateurs (.each).

if/unless .each
1.3 Avancé

3. 🚀 Blocs, Procs & Lambdas

Le cœur de Ruby. do |x| ... end. yield. Proc vs lambda.

Blocks yield Proc
1.4 Moyen

4. POO (Classes & Objets)

"Tout est objet". class, initialize, @var (instance), attr_accessor.

class POO
1.5 Avancé

5. POO (Modules & Mixins)

Héritage multiple via Module. include (instance) vs extend (classe).

Module Mixin include
2.1 Facile

6. Structures (Array)

[], %w[] (array de mots). .push (<<), .pop, .shift. Slicing ([1..3]).

Array <<
2.2 Moyen

7. Structures (Hash & Symbols)

{ key: 'val' } vs { :key => 'val' }. L'importance des Symbols (:key).

Hash Symbol
2.3 Avancé

8. Magie (Enumerables)

La puissance du module Enumerable. .map, .select, .reduce (.inject).

Enumerable .map
3.1 Facile

9. Gems & Bundler

gem install. Bundler (le "npm/pip" de Ruby). Gemfile & bundle install.

Gems Bundler Gemfile
3.2 Avancé

10. 🚂 Framework: Rails

Le "killer app". Convention over Configuration. ActiveRecord (ORM), MVC.

Rails ActiveRecord
3.3 Moyen

11. Gestion d'Erreurs

begin / rescue StandardError => e / ensure / end. raise "Erreur".

begin/rescue Errors
3.4 Moyen

12. Outils & Liens

IRB (Console), Rake (Tâches), ERB (Templates). Liens (RubyGems).

IRB Rake ERB
1.1 Philosophie, Syntaxe & Versions

Ruby est un langage de programmation interprété, dynamique, et purement orienté objet (une philosophie "tout est objet"). Il a été créé au milieu des années 90 par Yukihiro "Matz" Matsumoto.

La philosophie de Ruby est "le bonheur du développeur" (Developer Happiness). La syntaxe est conçue pour être élégante, lisible et "magique", en s'inspirant de Perl, Smalltalk, et Lisp.

Caractéristiques Clés
  • Typage Dynamique Fort : Comme Python, 5 + "hello" est une TypeError.
  • Tout est un Objet : Il n'y a pas de types primitifs. 5 est une instance de la classe Integer. "hello" est une instance de String.
  • Syntaxe Flexible : Les parenthèses () sont souvent optionnelles. Les ; sont inutiles.
  • Blocs : La "killer feature" de Ruby. C'est la base de ses itérateurs et de son élégance. (Voir 1.3).
Syntaxe de Base
# Commentaire
# Convention: snake_case pour les variables et méthodes
ma_variable = "Bonjour"
UN_CONSTANTE = 3.14 # Commence par une Majuscule

# Affichage (puts = put string + newline)
puts "Hello World"
p "Debug" # p est "inspect" (affiche les types) -> "Debug"

# Pas de parenthèses (optionnel)
puts "Hello"
# est égal à
puts("Hello")

# String interpolation (guillemets doubles)
nom = "Alice"
puts "Bonjour, #{nom.upcase}!" # "Bonjour, ALICE!"
Historique des Versions (10+ ans)
  • Ruby 1.8 (Legacy) : La version qui a propulsé Ruby on Rails. Très lente.
  • Ruby 1.9 (2007) : Réécriture majeure. Introduction de YARV (nouvelle VM), "hash rocket" (=>) devient optionnel, gestion des encodings.
  • Ruby 2.x (2013-2020) : Améliorations de performance, "keyword arguments", refinements.
  • Ruby 3.0 (2020) : Focus sur la concurrence (Ractors), typage statique (RBS, Sorbet), Hash nouvelle syntaxe ({ x: 1 }) devient la norme.
1.2 Contrôle de Flux (if/unless/loops/each)

Note : En Ruby, tous les blocs (if, def, while...) se terminent par le mot-clé end.

if / elsif / else
x = 10
if x > 20
  puts "Grand"
elsif x == 10
  puts "Moyen"
else
  puts "Petit"
end

# "If" inline (modificateur)
puts "C'est 10 !" if x == 10
unless (La magie de Ruby)

unless est l'inverse de if. C'est du "sucre syntaxique" pour if !(...).

is_admin = false

# Mauvais (difficile à lire)
if !is_admin
  puts "Accès refusé"
end

# Bon (Pythonic... euh, Ruby-esque)
unless is_admin
  puts "Accès refusé"
end
Boucles (while & .each)

Le for (for i in 0..5) existe, mais n'est jamais utilisé. La "vraie" boucle Ruby est l'itérateur .each, qui prend un bloc.

while / until
i = 0
while i < 3
  puts i
  i += 1
end
.each (La bonne façon)
fruits = ["pomme", "banane", "cerise"]

# Syntaxe multi-lignes (do...end)
fruits.each do |fruit|
  puts fruit.capitalize
end

# Syntaxe une ligne ({...})
fruits.each { |fruit| puts fruit.capitalize }
1.3 🚀 Blocs, Procs & Lambdas

Le "Bloc" est la fonctionnalité la plus puissante et la plus unique de Ruby. C'est un morceau de code anonyme que l'on peut "passer" à une méthode.

1. Le Bloc (Anonyme) & yield

Un bloc est *implicite*. Il ne peut pas être stocké dans une variable. On le "donne" à une méthode. La méthode l'exécute avec yield.

# 1. La méthode qui *accepte* un bloc
def ma_methode
  puts "Début de la méthode"
  # 'yield' exécute le bloc qui a été passé
  yield
  yield
  puts "Fin de la méthode"
end

# 2. On appelle la méthode en lui *donnant* un bloc
ma_methode do
  puts "-> Je suis le bloc !"
end

# Sortie:
# Début de la méthode
# -> Je suis le bloc !
# -> Je suis le bloc !
# Fin de la méthode
2. yield avec arguments
def ma_methode_args
  # On "passe" une valeur au bloc
  yield "Alice"
  yield "Bob"
end

ma_methode_args do |nom|
  puts "Bonjour, #{nom} !"
end

# Sortie:
# Bonjour, Alice !
# Bonjour, Bob !
3. Proc & lambda (Blocs "explicites")

Que faire si on veut *stocker* un bloc dans une variable ? On utilise un Proc (procédure) ou un lambda (une sorte de Proc plus strict).

# 1. Un Proc (stocke le bloc)
mon_proc = Proc.new { |x| puts "Proc dit: #{x}" }

# 2. Un Lambda (syntaxe "stabby arrow")
mon_lambda = ->(x) { puts "Lambda dit: #{x}" }

# 3. On peut les appeler
mon_proc.call(10) # "Proc dit: 10"
mon_lambda.call(20) # "Lambda dit: 20"

# 4. On peut les PASSER à une méthode (avec '&')
# '&' transforme le Proc en bloc implicite
["a", "b"].each(&mon_proc)
1.4 POO (Classes, Objets, Accessors)

En Ruby, **tout est objet**. Il n'y a pas de types primitifs. 5 est un objet (instance de Integer). "hello" est un objet (instance de String).

Classes, initialize, et @
  • class NomDeClasse : Définit une classe (convention : CamelCase).
  • def initialize : Le constructeur.
  • @variable : Une variable d'instance (privée).
  • @@variable : Une variable de classe (partagée, rare).
  • $variable : Une variable globale (à éviter).
Getters, Setters & attr_accessor

En Ruby, @variable est privée. On utilise des "accessors" (méthodes) pour y accéder.

La "Longue" Façon (Manuelle)
class User
  def initialize(name)
    @name = name
  end
  
  # Getter
  def name
    @name
  end
  
  # Setter
  def name=(new_name)
    @name = new_name
  end
end

u = User.new("Alice")
puts u.name # Appel du getter 'name'
u.name = "Bob" # Appel du setter 'name='
La "Bonne" Façon (attr_)

Ruby fournit des "macros" (des méthodes) pour écrire ces getters/setters à notre place.

class User
  # Crée le getter 'def name'
  attr_reader :name
  
  # Crée le setter 'def status='
  attr_writer :status

  # Crée getter ET setter pour 'email'
  attr_accessor :email

  def initialize(name, email)
    @name = name
    @email = email
    @status = "pending"
  end
end
1.5 POO (Modules & Mixins)

Ruby n'a pas d'héritage multiple (une classe ne peut hériter que d'UNE seule classe).
Le Problème : Comment partager des fonctionnalités communes (ex: marcher) entre Humain et Robot ?
La Solution : Les Mixins. Un Module est une collection de méthodes. Une Classe peut "inclure" un Module pour "mixer" (ajouter) ses méthodes.

include (Méthodes d'Instance)

include ajoute les méthodes du module en tant que méthodes d'instance (sur self).

# 1. Le Module (le "Mixin")
module Volant
  def voler
    puts "Je vole !"
  end
end

# 2. Les Classes
class Oiseau
  include Volant # "Mixe" les méthodes d'instance
end

class Avion
  include Volant
end

# 3. Utilisation
oiseau = Oiseau.new
avion = Avion.new

oiseau.voler # "Je vole !"
avion.voler # "Je vole !"
extend (Méthodes de Classe)

extend ajoute les méthodes du module en tant que méthodes de classe (sur LaClasse.methode).

module Finder
  def find_by_name(name)
    # ... logique de recherche
    puts "Recherche de #{name} dans #{self}"
  end
end

class User
  # On veut appeler User.find_by_name(...)
  extend Finder 
end

User.find_by_name("Alice")
# "Recherche de Alice dans User"
2.1 Structures (Array)

L'Array (liste) de Ruby est ordonné, indexé par 0, et mutable.

Création
# 1. Standard
arr = [1, 2, 3]

# 2. %w (Array de mots, pas de guillemets, pas d'interpolation)
fruits = %w[pomme banane cerise]
# (Identique à ["pomme", "banane", "cerise"])

# 3. %i (Array de symboles, idem)
symboles = %i[un deux trois]
# (Identique à [:un, :deux, :trois])
Méthodes Courantes (Modification)
arr = [1, 2, 3]

# Ajouter (push)
arr.push(4) # [1, 2, 3, 4]

# "Shovel" (identique à push, très idiomatique)
arr << 5 # [1, 2, 3, 4, 5]

# Retirer (le dernier)
arr.pop # 5 (renvoie l'élément)

# Retirer (le premier)
arr.shift # 1 (renvoie l'élément)

# Ajouter (au début)
arr.unshift(0) # [0, 2, 3, 4]
Accès & Slicing
arr = [10, 20, 30, 40, 50]

# Accès
arr[0] # 10
arr[-1] # 50
arr[99] # nil (Renvoie 'nil', ne plante PAS, != Python)
arr.at(0) # 10

# Slicing (Range)
arr[1..3] # [20, 30, 40] (Range INCLUSIF)
arr[1...3] # [20, 30] (Range EXCLUSIF)

# Slicing (Offset, Longueur)
arr[1, 3] # [20, 30, 40] (Index 1, prend 3 éléments)
2.2 Structures (Hash & Symbols)

Le Hash est la structure clé/valeur de Ruby (équivalent du dict Python).

Syntaxe : "Hash Rocket" (Legacy) vs "JSON-style" (Moderne)
1. Syntaxe "Hash Rocket" (=>)

Obligatoire si la clé n'est pas un Symbole (ex: un String, un Int).

# Clés de type String
user = {
  "nom" => "Alice",
  "age" => 30
}
puts user["nom"]
2. Syntaxe "JSON" (:)

Depuis Ruby 1.9. Plus propre. Ne fonctionne que si la clé est un Symbole.

# Clés de type Symbol (voir ci-dessous)
user = {
  nom: "Alice",
  age: 30
}
# (Identique à { :nom => "Alice", :age => 30 })

puts user[:nom]
Le "Symbol" (:key)

C'est le concept le plus confus de Ruby. Un Symbole n'est pas un String.

  • String ("hello") : Mutable. Chaque "hello" est un *nouvel* objet en mémoire.
  • Symbol (:hello) : Immutable. Chaque :hello est le *même* objet en mémoire. C'est un "label" ultra-rapide.

Règle : Toujours, *toujours* utiliser des Symbols comme clés de Hash (performance 10x).

Méthodes de Hash
user = { nom: "Alice", age: 30 }

# Accès
user[:nom] # "Alice"
user[:job] # nil (ne plante pas)
user.fetch(:job) # ERREUR (KeyError)
user.fetch(:job, "N/A") # "N/A" (défaut)

# Itération
user.each do |key, value|
  puts "#{key} = #{value}"
end
2.3 Magie (Le Module Enumerable)

C'est la *vraie* puissance de Ruby. Le module Enumerable est "mixé" (inclus) dans les Array, Hash, et Range. Il fournit des dizaines de méthodes d'itération incroyablement puissantes. (Similaire à LINQ ou Stream API).

Toutes ces méthodes prennent un bloc.

MéthodeDescription
.eachItération simple (le "for loop").
.map (ou .collect)Transforme chaque élément et renvoie un *nouvel* Array.
.select (ou .filter)Renvoie un *nouvel* Array contenant uniquement les éléments où le bloc renvoie true.
.rejectL'inverse de .select.
.reduce (ou .inject)"Réduit" la liste à une seule valeur (ex: une somme, un hash).
.find (ou .detect)Renvoie le *premier* élément où le bloc renvoie true.
.any? / .all?Renvoie true si *au moins un* / *tous les* éléments passent le test.
Exemple "Pythonic" vs "Ruby-esque"

Objectif : Obtenir la somme des carrés des nombres pairs de 1 à 10.

# Syntaxe "enchaînée" (chaîning)
resultat = (1..10)              # (1) Un Range
            .select { |n| n.even? } # (2) Sélectionne les pairs [2, 4, 6, 8, 10]
            .map { |n| n * n }      # (3) Met au carré [4, 16, 36, 64, 100]
            .reduce(0) { |sum, n| sum + n } # (4) Somme (avec 0 comme départ)

# 'reduce' est le plus puissant :
# (0, 4) -> 4
# (4, 16) -> 20
# (20, 36) -> 56
# ...
# Résultat : 220
3.1 Gems & Bundler (L'Écosystème)

L'écosystème de Ruby est géré par RubyGems (le dépôt de packages) et Bundler (le gestionnaire de dépendances).

OutilÉquivalent PythonDescription
GemPackage PyPIUne librairie/plugin (ex: rails, nokogiri).
RubyGemsPyPI (le site)Le dépôt (repository) central des gems.
gem installpip installLa commande pour installer un gem globalement.
Gemfilerequirements.txtUn fichier qui *définit* les dépendances du projet.
Bundlervenv + pipL'outil qui lit le Gemfile et installe les gems *localement* pour le projet.
Workflow (Bundler)

Bundler est l'équivalent de venv + requirements.txt. Il gère l'isolation et les dépendances.

1. Gemfile (Nouveau fichier)

À la racine du projet, on définit les dépendances.

# 1. Source (où chercher les gems)
source 'https://rubygems.org'

# 2. Version de Ruby
ruby '3.2.2'

# 3. Dépendances
gem 'rails', '~> 7.0.0' # '~>' = Version optimiste (>= 7.0, < 7.1)
gem 'pg' # (Pour PostgreSQL)

# 4. Groupes (dépendances de dev/test)
group :development, :test do
  gem 'rspec-rails' # (Pour les tests)
  gem 'pry-rails'   # (Pour le débug)
end
2. Installation
# 1. Installer bundler
$ gem install bundler

# 2. Installer les gems du Gemfile (localement)
$ bundle install

# 3. Exécuter un script (en utilisant les gems du bundle)
$ bundle exec rake db:migrate
3.2 🚂 Framework: Ruby on Rails

Ruby on Rails (ou "Rails") est le "killer app" de Ruby. C'est un framework web "full-stack" (backend + frontend) créé par David Heinemeier Hansson (DHH) en 2004.

Les 2 Philosophies Clés
  1. Convention over Configuration (CoC) (Convention > Configuration)
    Rails prend des milliers de décisions pour vous. (Ex: "Si ton modèle s'appelle User, ta table en BDD *doit* s'appeler users"). Vous n'avez pas à configurer cela. Si vous suivez les conventions, tout "marche magiquement".
  2. Don't Repeat Yourself (DRY) (Ne vous répétez pas)
    La logique doit être définie à un seul endroit. (Ex: ActiveRecord gère la validation, pas le contrôleur, ni la vue).
L'Architecture (MVC)
ComposantRôle (Description)
ActiveRecord (Model)L'ORM (Object-Relational Mapper). La "magie" de Rails. Une classe User est *directement* liée à la table users.
User.find(1) -> SELECT * FROM users WHERE id=1.
ActionController (Controller)Le "cerveau". Reçoit la requête HTTP (via routes.rb), parle au Modèle (@user = User.find(1)), et prépare les données pour la Vue.
ActionView (View)La "présentation". Fichiers .html.erb (Embedded Ruby). C'est du HTML avec du Ruby dedans (ex: <%= @user.name %>).
Autres Frameworks
  • Sinatra : L'équivalent de "Flask" (Python). Un micro-framework pour les petites APIs.
3.3 Gestion d'Erreurs (begin/rescue)

Ruby utilise une structure begin/rescue/ensure/end pour gérer les exceptions (similaire à try/catch/finally de Python/Java).

Attraper (begin/rescue)
# 1. 'begin' enveloppe le code à risque
begin
  # Lève une ZeroDivisionError
  resultat = 10 / 0 

# 2. 'rescue' attrape une erreur spécifique
rescue ZeroDivisionError => e
  puts "Erreur : Division par zéro ! (#{e.message})"
  resultat = 0

# 3. 'rescue' (sans type) attrape 'StandardError' (tout, sauf les erreurs système)
rescue => e
  puts "Erreur inconnue: #{e.class}"
  
# 4. 'else' s'exécute SI AUCUNE erreur n'a eu lieu
else
  puts "Calcul réussi."
  
# 5. 'ensure' s'exécute TOUJOURS (erreur ou non)
ensure
  puts "Fin du bloc begin/rescue."
end
Lever (raise)

On peut (et on doit) lever ses propres erreurs.

def set_age(age)
  unless age.is_a?(Integer)
    # 1. Lève (lance) une nouvelle exception
    raise TypeError, "L'âge doit être un entier"
  end
  
  if age < 0
    raise "L'âge ne peut pas être négatif." # (Crée une RuntimeError)
  end
end

# 'rescue' peut être utilisé en "modificateur"
set_age("vingt") rescue puts("Erreur capturée")
3.4 Outils, Liens & Cheatsheet
Outils (Ligne de commande)
OutilDescription
irbInteractive Ruby Bell. La console (REPL) de Ruby. (Équivalent python).
RakeRuby "Make". Un outil de "tâches" (build, tests, déploiement). (rake db:migrate dans Rails).
ERBEmbedded Ruby. Le système de templating (HTML) de la lib standard. (<%= ... %>).
RSpecLe framework de test BDD (Behavior-Driven) n°1. (describe/it/expect).
RuboCopLe "linter" et "formatter" n°1. (L'équivalent de Flake8 + Black de Python).
Cheatsheet (Idiomes)
# 'nil' est "falsey" (tout le reste est "truthy")
a = nil
if a 
  # Non
else
  # Oui
end

# Opérateur "Safe Navigation" (Ruby 2.3+)
# (Évite 'nil' error)
# Si @user est nil, renvoie nil (ne plante pas)
@user&.name

# Opérateur "||=" (Assignation conditionnelle)
# Si @nom est 'nil' ou 'false', l'assigner.
@nom ||= "Valeur par défaut"

# "Tap" (Pour débugger en chaînage)
(1..5).select { |n| n.even? }
      .tap { |arr| puts "Pairs: #{arr.inspect}" }
      .map { |n| n * 2 }