・ 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
・ 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.
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
>> 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
>> 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
>> 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
>> 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
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.
>> user = User.new
=> #<User id: nil, name: nil, email: nil, created_at: nil, updated_at: nil>
>> user.valid?
=> true
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.
>> 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"]
>> 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)"]
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.
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é.
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.
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é.
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.
>> 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"]}
>> 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)"]}
>> 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)"]}
-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
・ 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