Framework de Programmation des Serveurs Web

Initiation à Ruby on Rails (RoR)

Olivier Dalle (@unice.fr)

Université de Nice Sophia Antipolis

Rubyments: Rudiments de Ruby


  1. Ressources bibliographiques
  2. Exemple: retour au Layout
  3. Chaînes de caractères, méthodes
  4. Autres structures de données
  5. Les classes ruby

Ressources bibliographiques en ligne


Revenons au Layout


app/views/layouts/application.html.erb (vu chapitre 3):

Revenons au Layouts


Regardons cette ligne en particulier:
(inclusion application.css pour tous types de media)

Helpers


Rails permet d’ajouter des fonctions aux existantes: les helpers

Construisons un nouveau helper pour le titre:

Helpers


Rails permet d’ajouter des fonctions aux existantes: les helpers

Construisons un nouveau helper pour le titre:

Utilise le title fourni dans la définition de chaque page:

Helpers


Rails permet d’ajouter des fonctions aux existantes: les helpers

Construisons un nouveau helper pour le titre:

Que se passe-t-il si une page ne définit pas la variable title?

Helpers


Rails permet d’ajouter des fonctions aux existantes: les helpers

Construisons un nouveau helper pour le titre:

Que se passe-t-il si une page ne définit pas la variable title?

Ruby on Rails Tutorial Sample App |

Helpers


Rails permet d’ajouter des fonctions aux existantes: les helpers

Construisons un nouveau helper pour le titre:

Que se passe-t-il si une page ne définit pas la variable title?

Ruby on Rails Tutorial Sample App |

Avec une barre verticale inutile. Perfectionnons.

Helpers


Perfectionnons la définition du titre:

Helpers


Perfectionnons la définition du titre: app/helpers/application_helper.rb

Helpers


Perfectionnons la définition du titre: app/helpers/application_helper.rb

Helpers


Perfectionnons la définition du titre: app/helpers/application_helper.rb

Dans la page, le titre peut être simplifié: on remplace

Helpers


Perfectionnons la définition du titre: app/helpers/application_helper.rb

Dans la page, le titre peut être simplifié: on remplace

par

Helpers


Perfectionnons la définition du titre: app/helpers/application_helper.rb

app/views/layouts/application.html.erb devient:

Helpers


Perfectionnons la définition du titre: supprimons “Home” du titre de la page d’accueil.

On commence par …

Helpers


Perfectionnons la définition du titre: supprimons “Home” du titre de la page d’accueil.

On commence par … écrire les tests!

  1. La page doit contenir “Example App”:

Helpers


Perfectionnons la définition du titre: supprimons “Home” du titre de la page d’accueil.

On commence par … écrire les tests!

  1. La page doit contenir “Example App”:

Helpers


Perfectionnons la définition du titre: supprimons “Home” du titre de la page d’accueil.

On commence par … écrire les tests!

  1. La page doit contenir “Example App” (inchangé)
  2. La page doit avoir le titre de base

Helpers


Perfectionnons la définition du titre: supprimons “Home” du titre de la page d’accueil.

On commence par … écrire les tests!

  1. La page doit contenir “Example App” (inchangé)
  2. La page doit avoir le titre de base

Helpers


Perfectionnons la définition du titre: supprimons “Home” du titre de la page d’accueil.

On commence par … écrire les tests!

  1. La page doit contenir “Example App” (inchangé)
  2. La page doit avoir le titre de base

Helpers


Perfectionnons la définition du titre: supprimons “Home” du titre de la page d’accueil.

On commence par … écrire les tests!

  1. La page doit contenir “Example App” (inchangé)
  2. La page doit avoir le titre de base (corrigé)
  3. La page ne doit pas avoir un titre spécifique

Helpers


Perfectionnons la définition du titre: supprimons “Home” du titre de la page d’accueil.

On commence par … écrire les tests!

  1. La page doit contenir “Example App” (inchangé)
  2. La page doit avoir le titre de base (corrigé)
  3. La page ne doit pas avoir un titre spécifique

Helpers


Perfectionnons la définition du titre: supprimons “Home” du titre de la page d’accueil.

On commence par … écrire les tests!

  1. La page doit contenir “Example App” (inchangé)
  2. La page doit avoir le titre de base (corrigé)
  3. La page ne doit pas avoir un titre spécifique (nouveau)

Helpers


Perfectionnons la définition du titre: supprimons “Home” du titre de la page d’accueil.

On commence par … écrire les tests!

Et on lance les tests:

Helpers


Perfectionnons la définition du titre: supprimons “Home” du titre de la page d’accueil.

On commence par … écrire les tests!

Puis on lance les tests:

$ bundle exec rspec spec/requests/static_pages_spec.rb

Un test doit échouer.

Helpers


Perfectionnons la définition du titre: supprimons “Home” du titre de la page d’accueil.

On commence par … écrire les tests!

Puis on lance les tests: un test échoue.

On retire l’instruction provide…

Helpers


Perfectionnons la définition du titre: supprimons “Home” du titre de la page d’accueil.

On commence par … écrire les tests!

Puis on lance les tests: un test échoue.

On retire l’instruction provide… Et on relance les tests.

$ bundle exec rspec spec/requests/static_pages_spec.rb

Tous les tests au vert.

Helpers


Revenons à la définition du helper: app/helpers/application_helper.rb

Helpers


Revenons à la définition du helper: app/helpers/application_helper.rb

Plusieurs curiosités de ruby: modules, commentaires, variables locales, booléens, flots de contrôle, interpolation de chaines, valeurs de retour…

Console Ruby


Pour nous exercer nous allons utiliser la console ruby:

$ rails console
Loading development environment
>>

Commentaires


# Returns the full title on a per-page basis.
def full_title(page_title)
 .
 .
 .
end

Commentaires


Commentaires

# Returns the full title on a per-page basis.
def full_title(page_title)
 .
 .
 .
end
$ rails console
>> 17 + 42   # Integer addition
=> 59

Chaînes de Caractères


Chaînes de Caractères


Chaînes de Caractères


Chaînes de Caractères


Différentes approches possibles:

$ rails c
>> first_name = "Olivier"
=> "Olivier"
>> last_name = "Dalle"
=> "Dalle"
>> first_name + " " + last_name    # Concatenation, with a space in between
=> "Olivier Dalle"
>> "#{first_name} #{last_name}"    # The equivalent interpolation
=> "Olivier Dalle"

Affichage des Chaînes


Affichage des Chaînes


Affichage des Chaînes


Objets et appels de méthodes


Tout est objet dans ruby, y compris les chaînes et nil (!)


>> "foobar".length       
=> 6

Objets et appels de méthodes


Tout est objet dans ruby, y compris les chaînes et nil (!)


>> "foobar".length        # Passing the "length" message to a string
=> 6

Un appel de méthode est aussi appelé un envoi de message.

Objets et appels de méthodes


Convention: ? à la fin d’une méthode indique un résultat booléen.


>> s = "foobar"
>> if s.empty?
>>   "The string is empty"
>> else
>>   "The string is nonempty"
>> end
=> "The string is nonempty"

Opérateurs Booléens: &&, ||, !


>> x = "foo"
=> "foo"
>> y = ""
=> ""
>> puts "Both empty" if x.empty? && y.empty?
=> nil
>> puts "One  is empty" if x.empty? || y.empty?
"One is empty"
=> nil
>> puts "x is not empty" if !x.empty?
"x is not empty"
=> nil

Objets et appels de méthodes


Tout est objet dans ruby, y compris les chaînes et nil (!)

nil peut répondre à des méthodes. Par exemple:


>> nil.to_s
=> ""

Objets et appels de méthodes


Tout est objet dans ruby, y compris les chaînes et nil (!)

nil peut répondre à des méthodes. Mais pas toutes!


>> nil.empty?
NoMethodError: You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.empty?
>> nil.to_s.empty?      # Message chaining
=> true

Objets et appels de méthodes


Tout est objet dans ruby, y compris les chaînes et nil (!)

Une méthode permet de tester la nullité:


>> "foo".nil?
=> false
>> "".nil?
=> false
>> nil.nil?
=> true

if et unless inversés


Un if peut être construit à l’envers
→ améliore la lisibilité dans certains cas


puts "x is not empty" if !x.empty?

if et unless inversés


Un if peut être construit à l’envers
→ améliore la lisibilité dans certains cas


puts "x is not empty" if !x.empty?

Unless permet de tester la condition inverse:


>> string = "foobar"
>> puts "'#{string}' is nonempty." unless string.empty?
'foobar' is nonempty.
=> nil 

nil est particulier


Le seul objet ruby mis à part false qui a valeur fausse:


>> if nil
>>   true
>> else
>>   false        # nil is false
>> end
=> false

nil est particulier


Le seul objet ruby mis à part false qui a valeur fausse: → 0 (zéro) est VRAI!


>> if 0
>>   true        # 0 (and everything other than nil and false itself) is true
>> else
>>   false
>> end
=> true 

Définitions de méthodes


Ruby = langage de script:

Définitions de méthodes


Ruby = langage de script: toutes les instructions valides à la console.

 >> def string_message(string)
 >>   if string.empty?
 >>     "It's an empty string!"
 >>   else
 >>     "The string is nonempty."
 >>   end
 >> end
 => nil
 >> puts string_message("")
 It's an empty string!
 >> puts string_message("foobar")
 The string is nonempty.

Définitions de méthodes


Les méthodes de ruby ont une valeur de retour implicite:

Définitions de méthodes


Les méthodes de ruby ont une valeur de retour implicite:
la dernière instruction évaluée.

Définitions de méthodes


Les méthodes de ruby ont une valeur de retour implicite:
la dernière instruction évaluée.

Il existe aussi une instruction de retour explicite:


>> def string_message(string)
>>   return "It's an empty string!" if string.empty?
>>   return "The string is nonempty."
>> end

Définitions de méthodes


Les méthodes de ruby ont une valeur de retour implicite:
la dernière instruction évaluée.

Il existe aussi une instruction de retour explicite:


>> def string_message(string)
>>   return "It's an empty string!" if string.empty?
>>   return "The string is nonempty."
>> end

Le dernier return est inutile, mais rend le code plus lisible…

Retour au helper du titre…


On a fait le tour des spécificités du langage utilisées dans cet exemple:

module ApplicationHelper
  # Returns the full title on a per-page basis.       # Documentation comment
  def full_title(page_title)                          # Method definition
    base_title = "Ruby on Rails Tutorial Sample App"  # Variable assignment
    if page_title.empty?                              # Boolean test
      base_title                                      # Implicit return
    else
      "#{base_title} | #{page_title}"                 # String interpolation
    end
  end
end

Retour au helper du titre…


On a fait le tour des spécificités du langage utilisées dans cet exemple?

Retour au helper du titre…


On a fait le tour des spécificités du langage utilisées dans cet exemple? Presque:

 module ApplicationHelper 

Retour au helper du titre…


On a fait le tour des spécificités du langage utilisées dans cet exemple? Presque:

 module ApplicationHelper 

Tableaux


Exemple: découpage d’une chaîne:

 >>  "foo bar     baz".split     # Split a string into a three-element array
=> ["foo", "bar", "baz"] 

Tableaux


Exemple: découpage d’une chaîne:

 >>  "foo bar     baz".split     # Split a string into a three-element array
=> ["foo", "bar", "baz"] 

Ou avec un autre séparateur:

 >> "fooxbarxbazx".split('x')
=> ["foo", "bar", "baz"] 

Tableaux


Tableaux


Tableaux


Tableaux


Tableaux


Tableaux


Tableaux


Les Intervalles


Exemple : 0..9

Les Intervalles


Les Intervalles


Les Intervalles


Les blocs ruby


Aussi bien les intervalles que les tableaux savent répondre à des méthodes qui prennent des blocs:


(1..5).each { |i| puts 2 * i }
2
4
6
8
10
=> 1..5 

Les blocs ruby


Les blocs peuvent être délimités

Les blocs ruby


Les blocs peuvent être délimités

Les blocs ruby


Les blocs peuvent être délimités

Convention:

Les blocs par l’exemple…

 
>> 3.times { puts "Betelgeuse!" }   # 3.times takes a block with no variables.
"Betelgeuse!"
"Betelgeuse!"
"Betelgeuse!"
=> 3
>> (1..5).map { |i| i**2 }          # The ** notation is for 'power'.
=> [1, 4, 9, 16, 25]
>> %w[a b c]                        # Recall that %w makes string arrays.
=> ["a", "b", "c"]
>> %w[a b c].map { |char| char.upcase }
=> ["A", "B", "C"]
>> %w[A B C].map { |char| char.downcase }
=> ["a", "b", "c"]

Que fait ce code?


('a'..'z').to_a.shuffle[0..7].join

Que fait ce code?


('a'..'z').to_a.shuffle[0..7].join

Etape par étape:

>> ('a'..'z').to_a                     # An alphabet array
=> ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o",
"p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]

Que fait ce code?


('a'..'z').to_a.shuffle[0..7].join

Etape par étape:

>> ('a'..'z').to_a                     # An alphabet array
=> ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o",
"p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
>> ('a'..'z').to_a.shuffle             # Shuffle it.
=> ["c", "g", "l", "k", "h", "z", "s", "i", "n", "d", "y", "u", "t", "j", "q",
"b", "r", "o", "f", "e", "w", "v", "m", "a", "x", "p"]

Que fait ce code?


('a'..'z').to_a.shuffle[0..7].join

Etape par étape:

>> ('a'..'z').to_a                     # An alphabet array
=> ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o",
"p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
>> ('a'..'z').to_a.shuffle             # Shuffle it.
=> ["c", "g", "l", "k", "h", "z", "s", "i", "n", "d", "y", "u", "t", "j", "q",
"b", "r", "o", "f", "e", "w", "v", "m", "a", "x", "p"]
>> ('a'..'z').to_a.shuffle[0..7]       # Pull out the first eight elements.
=> ["f", "w", "i", "a", "h", "p", "c", "x"]

Que fait ce code?


('a'..'z').to_a.shuffle[0..7].join

Etape par étape:

>> ('a'..'z').to_a                     # An alphabet array
=> ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o",
"p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
>> ('a'..'z').to_a.shuffle             # Shuffle it.
=> ["c", "g", "l", "k", "h", "z", "s", "i", "n", "d", "y", "u", "t", "j", "q",
"b", "r", "o", "f", "e", "w", "v", "m", "a", "x", "p"]
>> ('a'..'z').to_a.shuffle[0..7]       # Pull out the first eight elements.
=> ["f", "w", "i", "a", "h", "p", "c", "x"]
>> ('a'..'z').to_a.shuffle[0..7].join  # Join them together to make one string.
=> "mznpybuj"

Tables de hachage (abbrv: hash)


Associent une clef à une valeur:

 >> user = {}                          # {} is an empty hash.
=> {}
>> user["first_name"] = "Michael"     # Key "first_name", value "Michael"
=> "Michael"
>> user["last_name"] = "Hartl"        # Key "last_name", value "Hartl"
=> "Hartl"
>> user["first_name"]                 # Element access is like arrays.
=> "Michael"
>> user                               # A literal representation of the hash
=> {"last_name"=>"Hartl", "first_name"=>"Michael"}

Tables de hachage


Définition groupée (avec => : hashrocket)

 user = { "first_name" => "Michael", "last_name" => "Hartl" }
=> {"last_name"=>"Hartl", "first_name"=>"Michael"}

Symboles


En ruby (et rails), les clefs sont souvent remplacées par des symboles:

Table de hachage avec symboles


On peut redéfinir une table comme suit:

 >> user = { :name => "Michael Hartl", :email => "michael@example.com" }
=> {:name=>"Michael Hartl", :email=>"michael@example.com"}
>> user[:name]              # Access the value corresponding to :name.
=> "Michael Hartl"
>> user[:password]          # Access the value of an undefined key.
=> nil

Table de hachage avec symboles


Une nouvelle syntaxe introduite avec ruby 1.9:

 >> h1 = { :name => "Michael Hartl", :email => "michael@example.com" }
=> {:name=>"Michael Hartl", :email=>"michael@example.com"}
>> h2 = { name: "Michael Hartl", email: "michael@example.com" }
=> {:name=>"Michael Hartl", :email=>"michael@example.com"} 
>> h1 == h2
=> true

Tables de hachage imbriquées


 >> params = {}        # Define a hash called 'params' (short for 'parameters').
=> {}
>> params[:user] = { name: "Michael Hartl", email: "mhartl@example.com" }
=> {:name=>"Michael Hartl", :email=>"mhartl@example.com"}
>> params
=> {:user=>{:name=>"Michael Hartl", :email=>"mhartl@example.com"}}
>>  params[:user][:email]
=> "mhartl@example.com"

Boucles sur les tables de hachage


Les table de hachage répondent à la méthode each:

 >> flash = { success: "It worked!", error: "It failed." }
=> {:success=>"It worked!", :error=>"It failed."}
>> flash.each do |key, value|
?>   puts "Key #{key.inspect} has value #{value.inspect}"
>> end
Key :success has value "It worked!"
Key :error has value "It failed."

La méthode inspect


Fournit une représentation litérale de l’objet sur lequel on l’invoque:

 >> puts (1..5).to_a            # Put an array as a string.
1
2
3
4
5
>> puts (1..5).to_a.inspect    # Put a literal array.
[1, 2, 3, 4, 5]
>> puts :name, :name.inspect
name
:name
>> puts "It worked!", "It worked!".inspect
It worked!
"It worked!"

La méthode inspect


Fournit une représentation litérale de l’objet sur lequel on l’invoque.

Il existe un raccourci:

 >> 
p :name             # Same as 'puts :name.inspect'
:name

Les classes ruby


Constructeurs:

>> s = “foobar”       # A literal constructor for strings using double quotes
=> “foobar”
>> s.class
=> String

Les classes ruby


Constructeurs:

>> s = String.new(“foobar”)   # A named constructor for a string
=> “foobar”
>> s.class
=> String
>> s == “foobar”
=> true

Les classes ruby


Constructeurs:

Les tableaux fonctionnent de la même facon:

>> a = Array.new([1, 3, 2])
=> [1, 3, 2]

Les classes ruby


Constructeurs:

Les tableaux fonctionnent de la même facon… mais pas les hashes:

>> h = Hash.new
=> {}
>> h[:foo]            # Try to access the value for the nonexistent key :foo.
=> nil
>> h = Hash.new(0)    # Arrange for nonexistent keys to return 0 instead of nil.
=> {}
>> h[:foo]
=> 0

Héritage entre classes


La méthode superclass retourne la classe parente:

>> s = String.new(“foobar”)
=> “foobar”
>> s.class                        # Find the class of s.
=> String
>> s.class.superclass             # Find the superclass of String.
=> Object
>> s.class.superclass.superclass  # Ruby 1.9 uses a new BasicObject base class
=> BasicObject 
>> s.class.superclass.superclass.superclass
=> nil

Héritage entre classes


La méthode superclass retourne la classe parente:

Exemple de classe


Un classe Mot avec une méthode palindrome?

>> class Mot
>>   def palindrome?(string)
>>     string == string.reverse
>>   end
>> end
=> nil

Exemple de classe


Un classe Mot avec une méthode palindrome?.

Exemple d’utilisation:

>> w = Word.new              # Make a new Word object.
=> #
>> w.palindrome?(“foobar”)
=> false
>> w.palindrome?(“level”)
=> true

Exemple de classe


Un classe Mot avec une méthode palindrome?.

On peut faire hériter cette classe de String:

>> class Word < String             # Word inherits from String.
>>   # Returns true if the string is its own reverse.
>>   def palindrome?
>>     self == self.reverse        # self is the string itself.
>>   end
>> end
=> nil

Exemple de classe


Un classe Mot avec une méthode palindrome?.

On peut faire hériter cette classe de String.
→ On récupère les méthodes de String:

>> s = Word.new(“level”)    # Make a new Word, initialized with “level”.
=> “level”                  
>> s.palindrome?            # Words have the palindrome? method.
=> true                     
>> s.length                 # Words also inherit all the normal string methods.
=> 5

Exemple de classe


Un classe Mot avec une méthode palindrome?.

On peut faire hériter cette classe de String.
→ On récupère les méthodes de String

>> s.class
=> Word
>> s.class.superclass
=> String
>> s.class.superclass.superclass
=> Object

Modification de classes existantes


Le problème:

>> “level”.palindrome?
NoMethodError: undefined method `palindrome?’ for level

Modification de classes existantes


Le problème:

>> “level”.palindrome?
NoMethodError: undefined method `palindrome?’ for level

Une solution existe?

Modification de classes existantes


Le problème:

>> “level”.palindrome?
NoMethodError: undefined method `palindrome?’ for level

Une solution existe? OUI!

>> class String
>>   # Returns true if the string is its own reverse.
>>   def palindrome?
>>     self == self.reverse
>>   end
>> end
=> nil
>> “deified”.palindrome?
=> true

Modification de classes existantes


A utiliser avec modération: Par exemple rails ajoute une méthode pour reconnaître une chaine vide.

>> "".blank?
=> true
>> "      ".empty?
=> false
>> "      ".blank?
=> true
>> nil.blank?
=> true

La classe Contrôleur


class StaticPagesController < ApplicationController

  def home
  end

  def help
  end

  def about
  end
end

La classe Contrôleur

>> controller = StaticPagesController.new
=> #
>> controller.class
=> StaticPagesController
>> controller.class.superclass
=> ApplicationController
>> controller.class.superclass.superclass
=> ActionController::Base
>> controller.class.superclass.superclass.superclass
=> ActionController::Metal
>> controller.class.superclass.superclass.superclass.superclass
=> AbstractController::Base
>> controller.class.superclass.superclass.superclass.superclass.superclass
=> Object

La classe Contrôleur

Une classe d’Utilisateurs


Créons example_user.rb:

class User
  attr_accessor :name, :email

  def initialize(attributes = {})
    @name  = attributes[:name]
    @email = attributes[:email]
  end

  def formatted_email
    "#{@name} <#{@email}>"
  end
end

Une classe d’Utilisateurs


Observons de près:

attr_accessor :name, :email

Crée des accesseurs pour les attributs nom et email:

Une classe d’Utilisateurs


Observons de près:

attr_accessor :name, :email

Crée des accesseurs pour les attributs nom et email:

Une classe d’Utilisateurs


Observons de près:

attr_accessor :name, :email

Crée des accesseurs pour les attributs nom et email.

Example d’utilisation:

example.name = "Example User"

Une classe d’Utilisateurs


Observons de près:
La méthode initialize(attributes = {})

Une classe d’Utilisateurs


Observons de près:
La méthode initialize(attributes = {})

Méthode spéciale en ruby: le constructeur.

Une classe d’Utilisateurs


Observons de près:
La méthode initialize(attributes = {})

Méthode spéciale en ruby: le constructeur.

La valeur par défaut des paramètres est un hash vide.

Une classe d’Utilisateurs


Observons de près:
La méthode initialize(attributes = {})

Méthode spéciale en ruby: le constructeur.

La valeur par défaut des paramètres est un hash vide.
→ Un hash retourne nil pour une clef inexistante

Une classe d’Utilisateurs


Observons de près:
La méthode initialize(attributes = {})

Méthode spéciale en ruby: le constructeur.

La valeur par défaut des paramètres est un hash vide.
→ Un hash retourne nil pour une clef inexistante

def initialize(attributes = {})
    @name  = attributes[:name]
    @email = attributes[:email]
  end

Une classe d’Utilisateurs


Observons de près:
La méthode initialize(attributes = {})

Méthode spéciale en ruby: le constructeur.

La valeur par défaut des paramètres est un hash vide.
→ Un hash retourne nil pour une clef inexistante
→ Initialise name et email a nil

Une classe d’Utilisateurs


Observons de près:

def formatted_email
   "#{@name} <#{@email}>"
end

Une classe d’Utilisateurs

Exemple d’utilisation: <font size ="+3">

>> require './example_user'     # This is how you load the example_user code.
=> ["User"]
>> example = User.new
=> #<User:0x224ceec @email=nil, @name=nil>
>> example.name                 # nil since attributes[:name] is nil
=> nil
>> example.name = "Example User"           # Assign a non-nil name
=> "Example User"
>> example.email = "user@example.com"      # and a non-nil email address
=> "user@example.com"
>> example.formatted_email
=> "Example User <user@example.com>"


>> require ‘./example_user’     # This is how you load the example_user code.
=> ["User"]
>> example = User.new
=> #<User:0×224ceec email=nil, @name=nil&gt;
&gt;&gt; example.name                 # nil since attributes[:name] is nil
=&gt; nil
&gt;&gt; example.name = &quot;Example User&quot;           # Assign a non-nil name
=&gt; &quot;Example User&quot;
&gt;&gt; example.email = &quot;userexample.com"      # and a non-nil email address
=> "user@example.com"
>> example.formatted_email
=> "Example User <user@example.com>"

Une classe d’Utilisateurs

Autre exemple d’utilisation: <font size ="+3">

>> user = User.new(name: "Michael Hartl", email: "mhartl@example.com")
=> #<User:0x225167c @email="mhartl@example.com", @name="Michael Hartl">
>> user.formatted_email
=> "Michael Hartl <mhartl@example.com>"


>> user = User.new(name: "Michael Hartl", email: "mhartl@example.com")
=> #<User:0×225167c email=&quot;mhartlexample.com", name=&quot;Michael Hartl&quot;&gt;
&gt;&gt; user.formatted_email
=&gt; &quot;Michael Hartl &lt;mhartlexample.com>"