・ 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.
Eh bien, chapitre 13. Il ne reste que deux chapitres au plus tôt. Cette fois, nous allons implémenter une fonction de publication de message utilisateur appelée Micropost. Bref, c'est Twitter. Soyons courageux! !! Cliquez ici pour la BGM d'aujourd'hui. ARIA vocal collection Je me demande si le moment viendra où vous pourrez travailler à distance tout en buvant un café latte à Neo Venezia ...
Exécutez Micropost.new sur la console Rails et affectez l'instance à la variable micropost. Essayez ensuite de remplacer l'identifiant du premier utilisateur par user_id et "Lorem ipsum" pour le contenu. Qu'y a-t-il dans les colonnes magiques (created_at et updated_at) de l'objet micropost à ce stade?
La route nommée dans le tableau 12.1 indique que _url doit être utilisé à la place de _path. Pourquoi, pensez-y. Conseil: pour la même raison que l'exercice que vous avez effectué dans l'activation de compte (11.1.1.1).
Sauvegardons l'objet micropost créé précédemment dans la base de données. Colonne magique à nouveau à ce stade → Don collectivement
>> micropost = Micropost.new(user_id: 1, content: "Lorem ipsum")
=> #<Micropost id: nil, content: "Lorem ipsum", user_id: 1, created_at: nil, updated_at: nil>
>> micropost.created_at
=> nil
>> micropost.updated_at
=> nil
>> micropost.user
User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ? [["id", 1], ["LIMIT", 1]]
=> #<User id: 1, name: "Example User", email: "[email protected]", created_at: "2020-09-17 08:34:09", updated_at: "2020-09-17 08:34:09", password_digest: "$2a$10$.EZN.AXBx91cG82BFOaKp.qpuwRpmG5N1JASh6KIBnv...", remember_digest: nil, admin: true, activation_digest: "$2a$10$mQpfXtRYM2s5JyNF243gYOln7RRrGaHHlilpOHouLfk...", activated: true, activated_at: "2020-09-17 08:34:09", reset_digest: nil, reset_sent_at: nil>
>> micropost.user.name
=> "Example User"
>> micropost.save
(0.1ms) SAVEPOINT active_record_1
SQL (1.3ms) INSERT INTO "microposts" ("content", "user_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["content", "Lorem ipsum"], ["user_id", 1], ["created_at", "2020-09-21 02:33:40.343372"], ["updated_at", "2020-09-21 02:33:40.343372"]]
(0.1ms) RELEASE SAVEPOINT active_record_1
=> true
>> micropost.created_at
=> Mon, 21 Sep 2020 02:33:40 UTC +00:00
>> micropost.updated_at
=> Mon, 21 Sep 2020 02:33:40 UTC +00:00
>> micropost = Micropost.new(user_id: " ", content: " ")
=> #<Micropost id: nil, content: " ", user_id: nil, created_at: nil, updated_at: nil>
>> micropost.valid?
=> false
>> micropost.errors.messages
=> {:user=>["must exist"], :user_id=>["can't be blank"], :content=>["can't be blank"]}
2. Ouvrez la console et essayez de créer un objet micropost avec un user_id vide et un contenu de 141 caractères ou plus. Assurons-nous que l'exécution valide? Sur cet objet échoue. De plus, qu'est-ce qui est écrit dans le message d'erreur généré? → Ci-dessous
>> micropost = Micropost.new(user_id: " ", content: "a" * 141)
=> #<Micropost id: nil, content: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...", user_id: nil, created_at: nil, updated_at: nil>
>> micropost.valid?=> false
>> micropost.errors.messages=> {:user=>["must exist"], :user_id=>["can't be blank"], :content=>["is too long (maximum is 140 characters)"]}
appartient à: appartient à ou moins. Le côté qui définit cela peut être utilisé comme méthode. has_many: placé du côté qui devient le parent avec la cravate.
>> user = User.first
User Load (0.1ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]]
=> #<User id: 1, name: "Example User", email: "[email protected]", created_at: "2020-09-17 08:34:09", updated_at: "2020-09-17 08:34:09", password_digest: "$2a$10$.EZN.AXBx91cG82BFOaKp.qpuwRpmG5N1JASh6KIBnv...", remember_digest: nil, admin: true, activation_digest: "$2a$10$mQpfXtRYM2s5JyNF243gYOln7RRrGaHHlilpOHouLfk...", activated: true, activated_at: "2020-09-17 08:34:09", reset_digest: nil, reset_sent_at: nil>
>> micropost = user.microposts.create(content: "Lorem ipsum")
(0.1ms) SAVEPOINT active_record_1
SQL (1.8ms) INSERT INTO "microposts" ("content", "user_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["content", "Lorem ipsum"], ["user_id", 1], ["created_at", "2020-09-21 03:35:41.329488"], ["updated_at", "2020-09-21 03:35:41.329488"]]
(0.1ms) RELEASE SAVEPOINT active_record_1
=> #<Micropost id: 1, content: "Lorem ipsum", user_id: 1, created_at: "2020-09-21 03:35:41", updated_at: "2020-09-21 03:35:41">
2. Un nouveau micro-message aurait dû être ajouté à la base de données lors de l'exercice précédent. Exécutons user.microposts.find (micropost.id) pour voir s'il a vraiment été ajouté. Aussi, que se passera-t-il si vous changez la partie micropost.id que vous venez d'exécuter en micropost? → Ci-dessous
>> user.microposts.find(micropost.id)
Micropost Load (0.2ms) SELECT "microposts".* FROM "microposts" WHERE "microposts"."user_id" = ? AND "microposts"."id" = ? LIMIT ? [["user_id", 1], ["id", 1], ["LIMIT", 1]]
=> #<Micropost id: 1, content: "Lorem ipsum", user_id: 1, created_at: "2020-09-21 03:35:41", updated_at: "2020-09-21 03:35:41">
>> user.microposts.find(micropost)
Traceback (most recent call last):
1: from (irb):6
ArgumentError (You are passing an instance of ActiveRecord::Base to `find`. Please pass the id of the object by calling `.id`.)
3. Qu'arrivera-t-il au résultat de l'exécution de user == micropost.user? Et qu'adviendra-t-il du résultat de l'exécution de user.microposts.first == micropost? → Ci-dessous
>> user == micropost.user
=> true
>> user.microposts.first == micropost
Micropost Load (0.2ms) SELECT "microposts".* FROM "microposts" WHERE "microposts"."user_id" = ? ORDER BY "microposts"."id" ASC LIMIT ? [["user_id", 1], ["LIMIT", 1]]
=> true
default_scope: utilisé lorsque vous souhaitez appliquer une étendue à toutes les requêtes du modèle. dependant :: destroy: mis à has_many. Lorsque le parent est supprimé, toutes les bases de données enfants associées sont supprimées. De plus, diverses choses sont apparues, je les ai donc résumées dans le glossaire.
>> Micropost.first.created_at
Micropost Load (0.1ms) SELECT "microposts".* FROM "microposts" ORDER BY "microposts"."created_at" DESC LIMIT ? [["LIMIT", 1]]
=> Mon, 21 Sep 2020 04:56:04 UTC +00:00
>> Micropost.last.created_at
Micropost Load (0.2ms) SELECT "microposts".* FROM "microposts" ORDER BY "microposts"."created_at" ASC LIMIT ? [["LIMIT", 1]]
=> Mon, 21 Sep 2020 04:55:35 UTC +00:00
2. Qu'advient-il de l'instruction SQL émise lors de l'exécution de Micropost.first? De même, qu'advient-il de Micropost.last? La chaîne de caractères affichée dans est l'instruction SQL. → Ci-dessous
>> Micropost.first
Micropost Load (0.2ms) SELECT "microposts".* FROM "microposts" ORDER BY "microposts"."created_at" DESC LIMIT ? [["LIMIT", 1]]
=> #<Micropost id: 2, content: "jaoivhiua", user_id: 2, created_at: "2020-09-21 04:56:04", updated_at: "2020-09-21 04:56:04">
>> Micropost.last
Micropost Load (0.1ms) SELECT "microposts".* FROM "microposts" ORDER BY "microposts"."created_at" ASC LIMIT ? [["LIMIT", 1]]
=> #<Micropost id: 1, content: "krutinb", user_id: 1, created_at: "2020-09-21 04:55:35", updated_at: "2020-09-21 04:55:35">
3. Affectez le premier utilisateur de la base de données à l'utilisateur variable. Quel est l'identifiant du micro-message que l'objet utilisateur a publié en premier? Ensuite, essayez de supprimer l'objet utilisateur à l'aide de la méthode destroy. Si vous le supprimez, vérifions dans Micropost.Find que le micropost associé à cet utilisateur est également supprimé. → Ci-dessous
>> user = User.first
User Load (0.1ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]]
=> #<User id: 1, name: "Example User", email: "[email protected]", created_at: "2020-09-17 08:34:09", updated_at: "2020-09-17 08:34:09", password_digest: "$2a$10$.EZN.AXBx91cG82BFOaKp.qpuwRpmG5N1JASh6KIBnv...", remember_digest: nil, admin: true, activation_digest: "$2a$10$mQpfXtRYM2s5JyNF243gYOln7RRrGaHHlilpOHouLfk...", activated: true, activated_at: "2020-09-17 08:34:09", reset_digest: nil, reset_sent_at: nil>
>> user.microposts.first.id
Micropost Load (0.2ms) SELECT "microposts".* FROM "microposts" WHERE "microposts"."user_id" = ? ORDER BY "microposts"."created_at" DESC LIMIT ? [["user_id", 1], ["LIMIT", 1]]
=> 1
>> user.destroy
(0.1ms) SAVEPOINT active_record_1
Micropost Load (0.1ms) SELECT "microposts".* FROM "microposts" WHERE "microposts"."user_id" = ? ORDER BY "microposts"."created_at" DESC [["user_id", 1]]
SQL (0.1ms) DELETE FROM "microposts" WHERE "microposts"."id" = ? [["id", 1]]
SQL (0.7ms) DELETE FROM "users" WHERE "users"."id" = ? [["id", 1]]
(0.1ms) RELEASE SAVEPOINT active_record_1
=> #<User id: 1, name: "Example User", email: "[email protected]", created_at: "2020-09-17 08:34:09", updated_at: "2020-09-17 08:34:09", password_digest: "$2a$10$.EZN.AXBx91cG82BFOaKp.qpuwRpmG5N1JASh6KIBnv...", remember_digest: nil, admin: true, activation_digest: "$2a$10$mQpfXtRYM2s5JyNF243gYOln7RRrGaHHlilpOHouLfk...", activated: true, activated_at: "2020-09-17 08:34:09", reset_digest: nil, reset_sent_at: nil>
>> Micropost.find(1)
Micropost Load (0.2ms) SELECT "microposts".* FROM "microposts" WHERE "microposts"."id" = ? ORDER BY "microposts"."created_at" DESC LIMIT ? [["id", 1], ["LIMIT", 1]]
Traceback (most recent call last):
1: from (irb):13
ActiveRecord::RecordNotFound (Couldn't find Micropost with 'id'=1)
Comme expliqué brièvement en 7.3.3, la méthode time_ago_in_words utilisée comme méthode d'assistance cette fois-ci peut être appelée depuis l'objet helper de la console Rails. Exécutons 3.weeks.ago et 6.months.ago en utilisant la méthode time_ago_in_words de cet objet d'assistance.
Quel type de résultat sera renvoyé lorsque vous exécuterez helper.time_ago_in_words (1.year.ago)? → Collectivement ci-dessous
>> helper.time_ago_in_words(3.weeks.ago)
=> "21 days"
>> helper.time_ago_in_words(6.months.ago)
=> "6 months"
>> helper.time_ago_in_words(1.year.ago)
=> "about 1 year"
3. Quelle est la classe de l'objet microposts Astuce: Comme vous pouvez le voir dans le code du Listing 13.23, récupérez d'abord l'objet avec la méthode paginate (l'argument est page: nil) puis appelez la méthode class. → Ci-dessous
s' for #<Class:0x0000000005968db8>)
>> user = User.first
User Load (0.2ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? [["LIMIT", 1]]
=> #<User id: 1, name: "Example User", email: "[email protected]", created_at: "2020-09-17 08:34:09", updated_at: "2020-09-17 08:34:09", password_digest: "$2a$10$.EZN.AXBx91cG82BFOaKp.qpuwRpmG5N1JASh6KIBnv...", remember_digest: nil, admin: true, activation_digest: "$2a$10$mQpfXtRYM2s5JyNF243gYOln7RRrGaHHlilpOHouLfk...", activated: true, activated_at: "2020-09-17 08:34:09", reset_digest: nil, reset_sent_at: nil>
>> microposts = user.microposts.paginate(page: nil)
Micropost Load (0.1ms) SELECT "microposts".* FROM "microposts" WHERE "microposts"."user_id" = ? ORDER BY "microposts"."created_at" DESC LIMIT ? OFFSET ? [["user_id", 1], ["LIMIT", 11], ["OFFSET", 0]]
=> #<ActiveRecord::AssociationRelation []>
>> microposts.class
=> Micropost::ActiveRecord_AssociationRelation
>> (1..10).to_a.take(6)
=> [1, 2, 3, 4, 5, 6]
2. La méthode to_a de l'exercice précédent est-elle vraiment nécessaire? → Vous pouvez le faire sans cela.
>> (1..10).take(6)
=> [1, 2, 3, 4, 5, 6]
3. Faker prend en charge une grande variété de cas autres que lorem ipsum. Apprenez à imprimer à l'écran tout en consultant la documentation Faker et imprimez le nom de l'université, le numéro de téléphone, les faits Hipster Ipsum et Chuck Norris à l'écran. (Traduction: Bien sûr, il prend également en charge le japonais, par exemple, il y a faker-okinawa qui génère des termes d'Okinawa. Veuillez jouer avec.) → Ci-dessous (Si vous budgétez faker-okinawa tel quel, une erreur se produira, alors commentez le fakergem normal avant de le regrouper.)
>> Faker::University.name
=> "East Abshire University"
>> Faker::PhoneNumber.cell_phone
=> "1-315-982-9239"
>> Faker::Hipster.sentence
=> "Mumblecore pug tilde marfa drinking 8-bit."
>> Faker::ChuckNorris.fact
=> "Chuck Norris can binary search unsorted data."
>> Faker::Okinawa::Awamori.name
=> "Mizuho"
Apparu à nouveau response.body. Contient du HTML complet. Utilisez assert_match pour trouver l'élément pertinent dans le HTML. Une méthode plus abstraite que assert_select. 'h1> img.gravatar' ⇨ Un nid appelé balise img avec la classe gravatar à l'intérieur de la balise h1.
ruby:show.thml.erb
<h1>
<%#= gravatar_for @user %>
<%#= @user.name %>
</h1>
2. Modifions le test du Listing 13.28 pour tester que will_paginate n'est affiché qu'une seule fois. Conseil: voir le tableau 5.2. → Ajoutez simplement le nombre; 1.
users_profile_test.rb
test "profile display" do
get user_path(@user)
assert_template 'users/show'
assert_select 'title', full_title(@user.name)
assert_select 'h1', text: @user.name
assert_select 'h1>img.gravatar'
assert_match @user.microposts.count.to_s, response.body
assert_select 'div.pagination', count: 1
@user.microposts.paginate(page: 1).each do |micropost|
assert_match micropost.content, response.body
end
end
ruby:home.thml.erb
<% if logged_in? %>
<%= render 'logged_in' %>
<% else %>
<%= render 'not_logged_in' %>
<% end %>
ruby:_logged_in.html.erb
<div class="row">
<aside class="col-md-4">
<section class="user_info">
<%= render 'shared/user_info' %>
</section>
<section class="micropost_form">
<%= render 'shared/micropost_form' %>
</section>
</aside>
</div>
ruby:_not_logged_in.html.erb
<div class="center jumbotron">
<h1>Welcome to the Sample App</h1>
<h2>
This is the home page for the
<a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a>
sample application.
</h2>
<%= link_to "Sign up now!", signup_path, class: "btn btn-lg btn-primary" %>
</div>
<%= link_to image_tag("rails.png ", alt: "Rails logo"),
'http://rubyonrails.org/' %>
2. Ouvrez la console et affectez le premier utilisateur de la base de données à la variable utilisateur. Essayez ensuite d'exécuter Micropost.where ("user_id =?", User.id), user.microposts et user.feed pour vous assurer qu'ils ont tous les mêmes résultats. Astuce: vous pouvez facilement savoir si les résultats sont identiques en comparant avec ==. → C'est pareil.
>> Micropost.where("user_id = ?", user.id) == user.microposts
Micropost Load (0.9ms) SELECT "microposts".* FROM "microposts" WHERE "microposts"."user_id" = ? ORDER BY "microposts"."created_at" DESC [["user_id", 1]]
Micropost Load (0.2ms) SELECT "microposts".* FROM "microposts" WHERE (user_id = 1) ORDER BY "microposts"."created_at" DESC
=> true
>> Micropost.where("user_id = ?", user.id) == user.feed
=> true
>> user.microposts == user.feed
Micropost Load (0.3ms) SELECT "microposts".* FROM "microposts" WHERE (user_id = 1) ORDER BY "microposts"."created_at" DESC
=> true
request.referrer méthode: renvoie l'URL précédente.
2. redirect_to request.referrer || root_Rediriger la ligne URL_back(fallback_location: root_url)Utilisons un navigateur pour vérifier qu'il fonctionne bien même si vous le remplacez par(Cette méthode est nouvelle de Rails 5)。 → Cela fonctionne.
2. Testons le nombre total de micro-messages affichés dans la barre latérale. À ce stade, vérifiez également si la forme singulière (micropost) et la forme plurielle (micropostes) sont affichées correctement. Conseil: utilisez le Listing 13.57 comme guide. → Est-ce que ça va?
microposts_interface_test.rb
test "micropost sidebar count" do
log_in_as(@user)
get root_path
assert_match "#{@user.microposts.count} microposts", response.body
other_user = users(:malory)
log_in_as(other_user)
get root_path
assert_match "0 microposts", response.body
other_user.microposts.create!(content: "A micropost")
get root_path
assert_match "1 micropost", response.body
end
2. Testez le téléchargeur d'images implémenté dans 13.4 en vous référant au modèle présenté dans l'extrait 13.63. Pour préparer le test, ajoutez d'abord un exemple d'image dans le répertoire fixture (exemple de commande: cp app / assets / images / rails.png test / fixtures /). Le test ajouté dans le listing 13.63 vérifie le téléchargement du fichier sur la page d'accueil et si l'image est affichée lorsque la publication est réussie. Notez que la méthode appelée fixture_file_upload dans le test est une méthode spéciale qui télécharge le fichier défini par fixture18. Conseil: pour vérifier si l'attribut d'image est valide, utilisez la méthode d'affectation introduite en 11.3.3. Cette méthode vous permettra d'accéder au micropost dans l'action de création après une publication réussie. → Ci-dessous. Le test ne devient pas VERT ici. Je ne trouve pas une pièce qui semble être fausse, alors je l'ai vérifiée et résolue. Reportez-vous à cet article Après avoir redémarré Spring, il est devenu VERT.
microposts_interface_test.rb
test "micropost interface" do
log_in_as(@user)
get root_path
assert_select 'div.pagination'
assert_select 'input[type="file"]'
#Transmission non valide
post microposts_path, params: { micropost: { content: "" } }
assert_select 'div#error_explanation'
#Transmission valide
content = "This micropost really ties the room together"
picture = fixture_file_upload('test/fixtures/rails.png', 'image/png')
assert_difference 'Micropost.count', 1 do
post microposts_path, params: { micropost: {
content: content,
picture: picture } }
end
assert assigns(:micropost).picture?
follow_redirect!
assert_match content, response.body
#Supprimer un message
assert_select 'a', text: 'delete'
first_micropost = @user.microposts.paginate(page: 1).first
assert_difference 'Micropost.count', -1 do
delete micropost_path(first_micropost)
end
#Accéder à différents profils d'utilisateurs(Assurez-vous qu'il n'y a pas de lien de suppression)
get user_path(users(:archer))
assert_select 'a', text: 'delete', count: 0
end
Que se passe-t-il si j'essaie d'envoyer un fichier image de 5 Mo ou plus?
Que se passe-t-il si j'essaie d'envoyer un fichier avec une extension non valide? → Dans les deux cas, il n'y a pas de fichier correspondant ... Vous obtiendrez probablement une erreur.
2. Si vous avez déjà ajouté les tests du Listing 13.63, vous pouvez obtenir un message d'erreur déroutant lors de l'exécution de la suite de tests à ce stade. Débarrassons-nous de cette erreur. Conseil: modifiez le fichier de configuration du listing 13.68 pour empêcher CarrierWave de redimensionner l'image pendant le test. → Je n'ai pas lancé d'erreur, mais je l'ai fait.
・ Micropost est également une ressource. -Lier les tables de données avec appartient_to et has_many. Le côté enfant peut être utilisé comme méthode. -Changé l'ordre d'affichage dans la portée par défaut. Quand j'ai recherché un article qui semblait faire attention à son utilisation, il est sorti. -Utilisez l'option dependant :: destroy pour supprimer l'objet associé et lui-même en même temps. -En utilisant ActiveRecord, le SQL brut est rarement utilisé. -Implémentation de téléchargement d'image avec CarrierWave. (Le stockage actif standard est-il maintenant?)
Fin de montage micropost ~ ~. Il y en avait beaucoup ici. Surtout le test et le faire lui-même sont souvent revus, mais il y en avait beaucoup. Maintenant, sample_app est aussi comme ça. Il est maintenant temps d'entrer dans le chapitre 14. Du suivi des utilisateurs à la mise en œuvre du flux de statut, c'est la dernière poussée!
⇨ Allez au chapitre 14! ⇦ Cliquez ici pour le chapitre 12 Cliquez ici pour les conditions préalables et le statut de l'auteur pour l'apprentissage
・ Proc Un objet d'un bloc ({} ou do ~ end). Les blocs ne sont pas des objets, vous devez donc en faire des objets avec proc. Voir ici
・ Portée (méthode) Une collection de requêtes spécifiques. Évitez d'écrire du code trop long encore et encore en rassemblant ce que vous utilisez plusieurs fois.
・ Type Lambda Fonction anonyme. Comme son nom l'indique, il s'agit d'une fonction sans nom.
・ Injection SQL Méthode d'attaque qui manipule illégalement le système de base de données en utilisant intentionnellement les lacunes de sécurité de l'application et en exécutant des instructions SQL que l'application n'anticipe pas. Aussi, une vulnérabilité qui permet l'attaque.
・ MIME (Extension de messagerie Internet polyvalente) Une norme qui permet de gérer divers formats par courrier électronique Internet, qui ne peut utiliser que du texte US-ASCII dans la norme.
Recommended Posts