[RUBY] (Giri) Un employé du gouvernement local dans la vingtaine travaille sur un didacticiel Rails [Chapitre 6]

supposition

・ Le tutoriel Rails est la 4ème édition ・ Cette étude est le 3e tour (2e tour après le chapitre 9) ・ L'auteur est un débutant qui a fait tout Progate

Politique de base

・ Si vous le lisez, vous ne le comprendrez pas. ・ Recherchez et résumez les termes que vous ne comprenez pas (en bas de l'article, glossaire). ・ Plongez dans ce que vous ne comprenez pas. ・ Travaillez sur tous les exercices. ・ Ne copiez pas le code autant que possible.

Ensuite, nous entrerons dans le chapitre 6. D'ici au chapitre 12, il semble que nous allons commencer à développer un système de connexion et d'authentification. C'est long, mais faisons-le.

Cliquez ici pour la chanson d'aujourd'hui. 17 ans et mur de Berlin "Prism" Je n'ai pas cultivé beaucoup de musique ces dernières années, mais je ne pense pas qu'il y aura un bon groupe de Shuge domestique.

[6.1.1 Exercice de migration de base de données]

  1. Rails utilise un fichier appelé schema.rb dans le répertoire db /. Il est utilisé pour suivre la structure de la base de données (appelée le schéma). Maintenant, vérifiez le contenu de db / schema.rb dans votre environnement et comparez-le avec le contenu du fichier de migration (extrait 6.2). → Je ne sais pas quelle est la bonne réponse, mais le contenu du fichier de migration est reflété.

2. Presque toutes les migrations peuvent être annulées (au moins dans ce didacticiel, toutes les migrations peuvent être annulées). L'annulation est appelée "rollback" et peut être réalisée dans Rails avec la commande db: rollback.

$ rails db:rollback

Après avoir exécuté la commande ci-dessus, vérifiez le contenu de db / schema.rb pour voir si la restauration a réussi (la colonne 3.1 résume également d'autres techniques de migration, veuillez donc vous y référer. S'il te plait donne moi). La commande ci-dessus appelle en interne la commande drop_table pour supprimer la table users de la base de données. Cela fonctionne car la méthode de changement sait que drop_table et create_table correspondent l'un à l'autre. La connaissance de cette correspondance facilite la migration inverse pour la restauration. Dans le cas d'une migration irréversible telle que la suppression d'une certaine colonne, il est nécessaire de définir séparément les méthodes de montée et de descente au lieu de la méthode de changement. Pour plus d'informations, consultez «Active Record Migration» dans le guide Rails. → Exécuter les rails db: migrer. Le contenu du schéma a disparu.

schema.rb


ActiveRecord::Schema.define(version: 0) do

end
  1. Exécutez à nouveau la commande rails db: migrate et vérifiez que le contenu de db / schema.rb a été restauré. → Je suis de retour!

[6.1.2 Exercice de fichier modèle]

  1. Ouvrez la console Rails et vérifiez que User.new crée un objet de classe User, et que l'objet hérite d'ApplicationRecord (conseil: utilisez la technique introduite dans 4.4.4). S'il vous plaît essayez).
  2. De la même manière, vérifiez que ApplicationRecord hérite d'ActiveRecord :: Base. → Exécutez les opérations suivantes sur la console.
>> user = User.new
=> #<User id: nil, name: nil, email: nil, created_at: nil, updated_at: nil>
>> user.class
=> User(id: integer, name: string, email: string, created_at: datetime, updated_at: datetime)
>> user.class.superclass
=> ApplicationRecord(abstract)
>> user.class.superclass.superclass
=> ActiveRecord::Base

[6.1.3 Exercice pour créer un objet utilisateur]

  1. Assurez-vous que user.name et user.email sont des instances de la classe String. → Aiyo.
>> user.name.class
=> String
>> user.email.class
=> String

2. Quelles instances de classe sont created_at et updated_at? → Les deux ActiveSupport :: TimeWithZone class (Cet article peut être utile)

>> user.created_at.class
=> ActiveSupport::TimeWithZone
>> user.updated_at.class
=> ActiveSupport::TimeWithZone

[6.1.4 Exercice de recherche d'objets utilisateur]

  1. Essayez de rechercher un objet utilisateur en utilisant le nom. Assurez-vous également de pouvoir utiliser la méthode find_by_name (les anciennes applications Rails verront souvent l'ancien type de find_by). → Ci-dessous
>> User.find_by(name: "shoji")
  User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."name" = ? LIMIT ?  [["name", "shoji"], ["LIMIT", 1]]
=> #<User id: 2, name: "shoji", email: "[email protected]", created_at: "2020-09-08 22:54:09", updated_at: "2020-09-08 22:54:09">
>> User.find_by_name("shoji")
  User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."name" = ? LIMIT ?  [["name", "shoji"], ["LIMIT", 1]]
=> #<User id: 2, name: "shoji", email: "[email protected]", created_at: "2020-09-08 22:54:09", updated_at: "2020-09-08 22:54:09">

2. Pour des raisons pratiques, User.all peut être traité comme un tableau, mais ce n'est pas réellement un tableau. Examinez l'objet généré par User.all et assurez-vous qu'il s'agit de la classe User :: ActiveRecord_Relation au lieu de la classe Array. → Ci-dessous (je vérifie auprès de la classe supérieure)

>> users = User.all
  User Load (0.2ms)  SELECT  "users".* FROM "users" LIMIT ?  [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<User id: 1, name: "miura", email: "[email protected]", created_at: "2020-09-08 22:53:59", updated_at: "2020-09-08 22:53:59">, #<User id: 2, name: "shoji", email: "[email protected]", created_at: "2020-09-08 22:54:09", updated_at: "2020-09-08 22:54:09">]>
>> users.class
=> User::ActiveRecord_Relation
>> users.class.superclass
=> ActiveRecord::Relation
>> users.class.superclass.superclass
=> Object
>> users.class.superclass.superclass.superclass
=> BasicObject
>> users.class.superclass.superclass.superclass.superclass
=> nil

3. Assurez-vous que lorsque vous appelez la méthode de longueur pour User.all, il vous sera demandé cette longueur (4.2.3). L'une des propriétés de Ruby est que vous pouvez en quelque sorte comprendre comment gérer les objets sans connaître la classe en détail. Cela s'appelle le typage du canard et est souvent exprimé dans la phrase suivante: "Si vous ressemblez à un canard et que vous sonnez comme un canard, c'est déjà un canard." À propos, dans le discours d'ouverture de RubyKaigi 2016, l'auteur de Ruby Matz a expliqué la frappe de canard. C'est une explication courte et facile à comprendre de 2-3 minutes, alors regardez-la!) → Le nombre de données s'affiche.

>> User.all.length
  User Load (0.2ms)  SELECT "users".* FROM "users"
=> 2

[6.1.5 Exercice de mise à jour des objets utilisateur]

  1. Mettez à jour à l'aide de l'attribut de nom en utilisant l'affectation à l'objet utilisateur et enregistrez-le avec save. → Ci-dessous
>> user1.name = "yongon"
=> "yongon"
>> user1.save
   (0.1ms)  SAVEPOINT active_record_1
  SQL (0.6ms)  UPDATE "users" SET "name" = ?, "updated_at" = ? WHERE "users"."id" = ?  [["name", "yongon"], ["updated_at", "2020-09-08 23:12:52.428275"], ["id", 1]]
   (0.1ms)  RELEASE SAVEPOINT active_record_1
=> true

2. Essayez maintenant de mettre à jour et d'enregistrer l'attribut de courrier électronique à l'aide de update_attributes. → Ce qui suit (l'identifiant de diverses erreurs est incorrect)

>> user1.update_attributes(name: "yongon", email: "[email protected]")
   (0.1ms)  SAVEPOINT active_record_1
  SQL (0.1ms)  UPDATE "users" SET "email" = ?, "updated_at" = ? WHERE "users"."id" = ?  [["email", "[email protected]"], ["updated_at", "2020-09-09 03:12:33.687572"], ["id", 4]]
   (0.1ms)  RELEASE SAVEPOINT active_record_1
=> true

3. De la même manière, veuillez vérifier que la colonne magique created_at peut également être mise à jour directement. Astuce: il est pratique d'utiliser "1.year.ago" lors de la mise à jour. C'est l'une des spécifications de temps de style Rails, et il calcule l'heure d'il y a un an à partir de l'heure actuelle. → Ci-dessous

>> user1.update_attribute(:created_at, 1.year.ago)
   (0.1ms)  SAVEPOINT active_record_1
  SQL (1.1ms)  UPDATE "users" SET "created_at" = ?, "updated_at" = ? WHERE "users"."id" = ?  [["created_at", "2019-09-09 03:18:24.829284"], ["updated_at", "2020-09-09 03:18:24.830017"], ["id", 4]]
   (0.1ms)  RELEASE SAVEPOINT active_record_1
=> true

[6.2.1 Notes et exercices pour vérifier l'efficacité]

Si vous utilisez la méthode de configuration, le processus écrit dans la méthode sera exécuté juste avant le test. Si vous définissez une variable d'instance dans ce champ, vous pouvez l'utiliser dans tous les tests.

  1. Depuis la console, confirmons que l'objet utilisateur nouvellement créé est valide. → Ci-dessous
>> user = User.new
=> #<User id: nil, name: nil, email: nil, created_at: nil, updated_at: nil>
>> user.valid?
=> true
  1. Vérifions si l'objet utilisateur créé en 6.1.3 est également valide. → La console est fermée une fois, elle disparaît donc. Je vais l'omettre car il est efficace de toute façon.

[6.2.2 Notes et exercices pour vérifier l'existence]

assert_not @ user.valid? Est-ce que RED → Il est facile de comprendre si vous pensez que "@user est valide?", Mais il y a un tsukkomi disant "Valide!". Comme il apparaît dans validates, {} peut être omis lors du passage d'un hachage comme dernier argument de la méthode.

  1. Créez un nouvel utilisateur u et vérifiez qu'il n'est pas valide au moment de la création. Pourquoi n'est-il pas valide? Vérifions le message d'erreur. → La validation fonctionne car ni le nom ni l'adresse e-mail ne sont saisis.
>> u = User.new
=> #<User id: nil, name: nil, email: nil, created_at: nil, updated_at: nil>
>> u.valid?
=> false
>> u.errors.full_messages
=> ["Name can't be blank", "Email can't be blank"]

2. Exécutez u.errors.messages et vérifiez que les erreurs peuvent être obtenues au format de hachage. Comment puis-je obtenir uniquement les informations d'erreur relatives aux e-mails? → J'ai écrit sur cette page. . Messages C'est pareil avec ou sans lui.

>> u.errors.messages
=> {:name=>["can't be blank"], :email=>["can't be blank"]}
>> u.errors[:email]
=> ["can't be blank"]
>> u.errors.messages[:email]
=> ["can't be blank"]

[6.2.3 Exercice de vérification de la longueur]

  1. Créez un objet utilisateur avec un nom et un attribut d'e-mail trop longs et vérifiez qu'il n'est pas valide.
  2. Quel type de message d'erreur sera généré lorsque la validation de la longueur échoue? Veuillez vérifier. → Collectivement ci-dessous
>> user = User.new(name: "a"*55, email: "e"*244 + "@example.com")
=> #<User id: nil, name: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...", email: "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee...", created_at: nil, updated_at: nil>
>> user.valid?=> false
>> user.errors.full_messages=> ["Name is too long (maximum is 50 characters)", "Email is too long (maximum is 255 characters)"]

[6.2.4 Exercice de vérification du format]

Dois-je me souvenir des expressions régulières? C'est compliqué, il vaut donc mieux le vérifier et le mettre en œuvre à chaque fois.

  1. Essayez de publier la liste des adresses e-mail valides dans le Listing 6.18 et la liste des adresses e-mail non valides dans le Listing 6.19 dans votre Rubulaire Votre chaîne de test:. Essayez ensuite de publier l'expression régulière du Listing 6.21 dans Votre expression régulière: pour vous assurer que seules les adresses e-mail valides correspondent et non toutes les adresses e-mail non valides. → Vérifiez simplement.

2. Comme mentionné précédemment, l'expression régulière qui vérifie l'adresse e-mail dans le Listing 6.21 autorise les adresses e-mail invalides avec des points consécutifs, comme foo @ bar..com. Tout d'abord, ajoutez cette adresse e-mail à la liste des adresses e-mail non valides dans le Listing 6.19 et assurez-vous que cela entraîne l'échec du test. Utilisez ensuite l'expression canonique légèrement plus complexe présentée dans l'extrait 6.23 pour vérifier que ce test réussit. → Faites cela aussi.   3. Ajoutez foo @ bar..com à la liste des adresses e-mail Rubular et essayez d'utiliser les expressions régulières du Listing 6.23 de Rubular. Assurez-vous que seules les adresses e-mail valides correspondent et non toutes les adresses e-mail invalides. → Confirmé.

[6.2.5 Notes et exercices pour vérifier le caractère unique]

Le contenu ici est un peu déroutant, mais le fait est que l'adresse e-mail est définie pour être insensible à la casse. Le test garantit-il que les utilisateurs en majuscules ne sont pas valides (la même adresse en majuscules)? Et une méthode de rappel a été introduite pour tout rendre plus bas avant que l'adresse e-mail ne soit stockée dans la base de données. Après un rapide coup d'œil, l'utilisation de rappels semble être prudente. Il semble que vous devriez éviter les branchements conditionnels dans le rappel.

  1. Ajoutons un test pour abaisser l'adresse e-mail au Listing 6.26, comme indiqué dans le Listing 6.33. Par ailleurs, dans le code de test à ajouter, la méthode de rechargement qui se met à jour en fonction de la valeur de la base de données et la méthode assert_equal qui vérifie si les valeurs correspondent sont utilisées. Pour voir si les tests de l'extrait 6.33 fonctionnent, commentons la ligne before_save pour qu'elle devienne rouge, et décommentons-la pour qu'elle devienne verte. → Exécutez comme indiqué. Puisqu'il est converti en minuscules avant d'être enregistré avec before_save, il devient ROUGE lorsqu'il est commenté et VERT lorsqu'il est annulé.

  2. Réécrivons le rappel before_save dans email.downcase! Tout en vérifiant le résultat de l'exécution de la suite de tests. Astuce: Vous pouvez modifier l'attribut email directement en ajoutant un! À la fin de la méthode (extrait 6.34). → Le "!" Qui apparaît ici représente un processus destructeur. Cela signifie que votre adresse e-mail restera convertie en minuscules. Même s'il est réécrit, le test est VERT.

[6.3.2 Exercice où l'utilisateur a un mot de passe sécurisé]

  1. À ce stade, assurez-vous que même si vous donnez un nom et une adresse e-mail valides à l'objet utilisateur, il échouera avec valid?.
  2. Pourquoi échoue-t-il? Consultez le message d'erreur. → Je vais le mettre ensemble! Vous ne pouvez pas avoir de mot de passe vide.
>> user = User.new(name: "kote", email: "[email protected]")
=> #<User id: nil, name: "kote", email: "[email protected]", created_at: nil, updated_at: nil, password_digest: nil>
>> user.valid?
  User Exists (0.2ms)  SELECT  1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER(?) LIMIT ?  [["email", "[email protected]"], ["LIMIT", 1]]
=> false
>> user.errors.messages
=> {:password=>["can't be blank"]}

[6.3.3 Nombre minimum de caractères pour l'exercice du mot de passe]

  1. Même avec un nom et une adresse e-mail valides, assurez-vous que l'objet utilisateur ne sera pas valide si le mot de passe est trop court.
  2. Quel type de message d'erreur obtiendrez-vous si vous échouez ci-dessus? → Je vais aussi résumer cette fois! Bien sûr, si le mot de passe est trop court, vous vous fâcherez. Vous pouvez voir que has_secure_password fonctionne ici et que le mot de passe est haché.
>> user = User.new(name: "kote", email: "[email protected]", password: "kotte")
=> #<User id: nil, name: "kote", email: "[email protected]", created_at: nil, updated_at: nil, password_digest: "$2a$10$7Svz/KnRoF7zab0PnhKFL.n/OsSltRvvREHECcmuq.D...">
>> user.valid?  User Exists (0.2ms)  SELECT  1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER(?) LIMIT ?  [["email", "[email protected]"], ["LIMIT", 1]]
=> false
>> user.errors.messages=> {:password=>["is too short (minimum is 6 characters)"]}

[6.3.4 Création d'utilisateur et exercice d'authentification]

  1. Redémarrez la console une fois (supprimez l'objet utilisateur) et essayez de rechercher l'objet utilisateur créé dans cette section. → Ci-dessous
>> user = User.find(1)
  User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
=> #<User id: 1, name: "Michael Hartl", email: "[email protected]", created_at: "2020-09-10 02:37:56", updated_at: "2020-09-10 02:37:56", password_digest: "$2a$10$A5n.HFBigQfwnWVJZw2N0e4M9sxPaR8ndLZwqtZWYS7...">

2. Si vous pouvez trouver l'objet, remplacez le nom par une nouvelle chaîne de caractères et essayez de mettre à jour avec la méthode save. Ça ne marche pas ... pourquoi ça n'a pas marché? → Ci-dessous. La méthode save essaie de mettre à jour tous les attributs, il semble donc qu'une erreur soit générée lors de la mise à jour du mot de passe.

>> user.name = "meshino"
=> "meshino"
>> user.save
   (0.1ms)  begin transaction
  User Exists (0.2ms)  SELECT  1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER(?) AND ("users"."id" != ?) LIMIT ?  [["email", "[email protected]"], ["id", 1], ["LIMIT", 1]]
   (0.0ms)  rollback transaction
=> false
>> user.errors.messages
=> {:password=>["can't be blank", "is too short (minimum is 6 characters)"]}

3. Essayez maintenant de mettre à jour le nom de l'utilisateur en utilisant la technique introduite en 6.1.5. → Alors, mettez à jour en utilisant update_attribute. (Cependant, puisque l'utilisateur qui a lancé l'erreur plus tôt est réutilisé, il n'est pas valide même après la mise à jour du nom. Il semble que le mot de passe doit être réinitialisé.)

>> user.update_attribute(:name, "nakamura")
   (0.1ms)  begin transaction
  SQL (4.2ms)  UPDATE "users" SET "name" = ?, "updated_at" = ? WHERE "users"."id" = ?  [["name", "nakamura"], ["updated_at", "2020-09-10 03:07:11.190666"], ["id", 1]]
   (6.4ms)  commit transaction
=> true
>> user.valid?
  User Exists (0.2ms)  SELECT  1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER(?) AND ("users"."id" != ?) LIMIT ?  [["email", "[email protected]"], ["id", 1], ["LIMIT", 1]]
=> false
>> user.errors.messages=> {:password=>["can't be blank", "is too short (minimum is 6 characters)"]}

Résumé du chapitre 6

-Créer une migration et migrer chaque fois que vous mettez à jour la base de données. ・ Active Record est pratique. Rails est en baisse, mais Active Record a été écrit quelque part avec ses avantages. -Définir le contenu d'entrée invalide dans la validation et la lecture. ・ Je pense qu'il suffit de reconnaître que les expressions régulières sont probablement de telles choses. -Amélioration de l'efficacité de la recherche en ajoutant un index à la base de données. L'unicité est également garantie. -Puisque has_secure_password est utilisé par les gemmes, je me demande si d'autres gemmes pratiques peuvent être utilisées pour implémenter un traitement sécurisé. Quand je l'ai cherché, il est sorti après tout. Apprenons à partir de maintenant.

Cela prend du temps car j'enquête sur diverses préoccupations en faisant un détour. Cependant, je ne pense pas que le contenu du tutoriel seul fonctionnera, donc je serai également intéressé par diverses autres choses. Et bien ensuite! Le chapitre 7 est la mise en œuvre de l'enregistrement des utilisateurs! s'inscrire!

Allez au chapitre 7! Cliquez ici pour le chapitre 5 Cliquez ici pour les conditions préalables et le statut de l'auteur pour l'apprentissage

Glossaire qui saisit en quelque sorte l'image

・ Assert_not Puisqu'il est nié par non, cela signifie le contraire. Si la cible est vraie, elle échoue, si elle est fausse, elle réussit.

· Rappel d'enregistrement actif Vous pouvez définir une méthode à appeler avant / après certains traitements. Pour plus d'informations, consultez le Guide des rails. ](Https://railsguides.jp/active_record_callbacks.html)

·bout Un substitut à préparer au moment du test. Le substitut appelé à partir du processus testé est le stub et le substitut qui appelle le processus testé est le pilote.

Recommended Posts

(Giri) Un employé du gouvernement local dans la vingtaine travaille sur un tutoriel Rails [Chapitre 11]
(Giri) Un employé du gouvernement local dans la vingtaine travaille sur un didacticiel Rails [Chapitre 1]
(Giri) Un employé du gouvernement local dans la vingtaine travaille sur un didacticiel Rails [Chapitre 14]
(Giri) Un employé du gouvernement local dans la vingtaine travaille sur un didacticiel Rails [Chapitre 12]
(Giri) Un employé du gouvernement local dans la vingtaine travaille sur un didacticiel Rails [Chapitre 5]
(Giri) Un employé du gouvernement local dans la vingtaine travaille sur un didacticiel Rails [Chapitre 3]
(Giri) Un employé du gouvernement local dans la vingtaine travaille sur un didacticiel Rails [Chapitre 4]
(Giri) Un employé du gouvernement local dans la vingtaine travaille sur un didacticiel Rails [Chapitre 8]
(Giri) Un employé du gouvernement local dans la vingtaine travaille sur un didacticiel Rails [Chapitre 6]
(Giri) Un employé du gouvernement local dans la vingtaine travaille sur un didacticiel Rails [Chapitre 13]
(Giri) Un employé du gouvernement local dans la vingtaine travaille sur un didacticiel Rails [Chapitre 9]
(Giri) Un employé du gouvernement local dans la vingtaine travaille sur un didacticiel Rails [Chapitre 10]
(Giri) Un employé du gouvernement local dans la vingtaine travaille sur un didacticiel Rails [Chapitre 7]
(Giri) Un employé du gouvernement local dans la vingtaine travaille sur un didacticiel Rails [Chapitre 2]
(Giri) Un employé du gouvernement local dans la vingtaine travaille sur un didacticiel Rails [Introduction]
[Tutoriel Rails Chapitre 5] Créer une mise en page
(Ruby on Rails6) Création de données dans une table
tutoriel rails Chapitre 6
tutoriel rails Chapitre 1
tutoriel rails Chapitre 7
tutoriel rails Chapitre 5
tutoriel rails Chapitre 10
tutoriel rails Chapitre 9
tutoriel rails Chapitre 8
[Tutoriel Rails Chapitre 2] Que faire lorsque vous faites une erreur dans le nom de la colonne
Mémorandum du didacticiel Rails (Chapitre 3, 3.1)
Tutoriel Rails Chapitre 4 Apprentissage
Tutoriel Rails Chapitre 1 Apprentissage
Tutoriel Rails Chapitre 2 Apprentissage
Difficultés à créer un environnement Ruby on Rails (Windows 10) (SQLite3)
Comment afficher des graphiques dans Ruby on Rails (LazyHighChart)
Appliquer le CSS à une vue spécifique dans Ruby on Rails