[Une nuit au cinéma] 6. Erreur! Erreur!


#1

Hello,

Jusque là ça allait sur cet exercice mais je suis bloqué sur la partie 6 de ce chapitre. En m'aidant de l'exemple auquel on fait réference tout au long de l'excercice j'ai vu qu'il faut idéalement utiliser if films[titre.to_sym].nil? afin de vérifier si le film est déjà présent au sein de ma librairie.

Alors oui je peux valider l'excercice mais je souhaite comprendre pourquoi et comment vérifier qu'une nouvelle entrée est présente ou nom au sein d'un hash créé plus tôt.

Voici l'état d'avancement de mon code, si vous avez des suggestions pour l'améliorer ou le rendre plus clean n'hésitez pas :slight_smile:

films = {
    Avatar: 3,
    Casino_Royal: 2,
    Millenium: 4
}
puts "Bienvenue, que souhaitez vous faire?"
choix = gets.chomp

case choix
when "ajouter"
   puts "Merci de saisir le nom du film que vous souhaitez ajouter"
   titre = gets.chomp
   titre.to_sym
   puts "Quelle note voulez-vous lui attribuer ? (entrer un chiffre entre 0 et 10.)"
   note = gets.chomp
   note.to_i
films[titre.to_sym] = note.to_i
puts "Vous venez d'ajouter avec succès le film #{titre} dont la note est #{note}"

when "modifier"
    puts "Modifié !"
when "afficher"
    puts "  Films !"
when "supprimer"
    puts "Supprimé !"
else 
    puts "Erreur !"
end

Merci pour votre aide !
Nicolas

`


#2

Entre temps j'ai trouvé cette solution qui me permet également de faire tourner le programme comme attendu.

if 
films[titre.to_sym] == nil
puts "Vous venez d'ajouter avec succès le film #{titre} dont la note est #{note}"

else 
puts "Ce film existe déjà!"
end

Sans grande conviction que ça soit la meilleure façon de l'écrire, any help ?
Thanks.


#3

Hey,
je l'écrirais plutôt comme ceci:

if films[titre.to_sym].nil?

Avec le reste du code

case choix
when "ajouter"
puts "Merci de saisir le nom du film que vous souhaitez ajouter :"
titre = gets.chomp
  if films[titre.to_sym].nil?
    puts "Quelle note souhaitez-vous lui attribuer ?"
    note = gets.chomp
    films[titre.to_sym] = note.to_i
    puts "Vous venez d'ajouter avec succès le film #{titre} dont la note est #{note}."
  else
    puts "Ce film existe déjà."
  end

Le if vérifie que le film n'existe pas déjà. S'il existe, il renvoie à else qui indique que le film existe déjà.
Si le film n'existe pas encore, on demande directement une note.
Dès qu'on a le titre du film et la note, on envoie le tout dans le hash films et on valide avec le message succès.

N'hésites pas si tu as des questions. Good luck!


#4

Hey @ghostlovescore

Merci pour ton aide, du coup voici le morceau de code pour le case "ajout d'un film" avec lequel j'ai validé l'exercice:
Quelques questions plus bas qui me viennent en comparant avec ton code :slight_smile:

case choix
when "ajouter"
   puts "Merci de saisir le nom du film que vous souhaitez ajouter:"
   titre = gets.chomp
   titre.to_sym
   puts "Quelle note voulez-vous lui attribuer ? (entrer un chiffre entre 0 et 10.)"
   note = gets.chomp
   note.to_i
if 
films[titre.to_sym] == nil
puts "Vous venez d'ajouter avec succès le film #{titre} dont la note est #{note}"

else 
puts "Ce film existe déjà!"
end

1. Utiliser if films[titre.to_sym].nil? à la place de films[titre.to_sym] == nil

=> La méthode .nil? on l'avait déjà vu plus tôt dans cette track Ruby ?
=> Cette méthode doit toujours être accompagnée d'un "?" à la fin ?
=> Concretement tu me conseilles d'utiliser systématiquement .nil? pour vérifier qu'un élement est présent au sein d'un hash ? d'un tableau ? Ça fonctionne pour tous les types de structures de données ?

2. Conversion des strings en symboles

Une fois le titre et la note du nouveau film récupérés avec gets.chomp, tu transformes la string en symbole au tout dernier moment en ajoutant cette nouvelle paire au sein du hash films. De mon côté j'ai l'impression de faire des choses en double, je m'explique:

case choix
when "ajouter"
   puts "Merci de saisir le nom du film que vous souhaitez ajouter:"
   titre = gets.chomp
   **titre.to_sym**
   puts "Quelle note voulez-vous lui attribuer ? (entrer un chiffre entre 0 et 10.)"
   note = gets.chomp
   **note.to_i**

En gras les deux passages où je convertie les strings titre puis note en symboles. Sauf que je le fais de nouveau au moment de l'ajout de cette paire dans mon hash films. Je peux supprimer ces 2 lignes en gras sans que ça ai d'impact ? En réalité la question est de savoir si je peux me contenter de transformer les strings sauvées en symboles au dernier moment lors de leurs ajout ?

Sinon je comprends bien le reste et je préfère ta vision du else qui ne possède aucune intélligence, toute la réflexion est dans le if et ça me semble plus simple après coup :wink:

Thanks !!
Nico


#5

Hello,

  1. Comme tu l'auras constaté, .nil? est identique à == nil
    Cependant, je préfère rester constant et utiliser .nil? car tu verras qu'on peut utiliser ce type de méthode à plusieurs sauces (.even? .odd?). C'est un peu le même principe à assimiler que les divers .to_sym .to_a .to_i etc.
    C'est un peu la force de Ruby, qui nous demande très clairement .even? est-ce un nombre pair?

  2. Effectivement, tu répètes plusieurs fois la méthode. Tu verras plus tard le concept de "Refactoring code", qui consiste à simplifier le plus possible et donc se débarrasser des choses inutiles et doublons dans son code. Ici comme tu l'avais deviné la transformation se fait lors de l'ajout au Hash films[titre.to_sym] = note.to_i (ça dit: envoyer à films le key (titre) transformé en symbole qui a pour value (note) transformé en nombre entier.

Avec le temps on parvient à simplifier son code au maximum (ce qui dans un premier temps semble plus complexe, car pour l'apprentissage il est plus simple de tout définir ligne par ligne pour en comprendre la logique). N'hésites pas à constamment te poser la question "comment pourrais-je rendre ce code plus simple?"

Un excellent exemple :

my_array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

my_array.each do |n|
   puts n if n % 2 == 0
end

devient
my_array.each { |n| puts n if n % 2 == 0 }

devient
my_array.each { |n| puts n if n.even? }

devient
my_array.each.select { &:even? }

Bon... je m'égare légèrement, mais ça montre bien les possibilités de refactoring avec Ruby + l'utilisation de .even?

Hope all this made sense...
Have fun!


#6

Je me garde la puissance du .even? sous le coude pour plus tard :slight_smile:
Thanks pour l'explication, ça n'a jamais été aussi clair merci beaucoup !