J'ai rencontré un bug qui n'était pas mentionné dans le matériel lors de son intégration dans le didacticiel Rails. Recherchez la cause du bogue et résumez la solution.
-Comment vérifier le nom de la colonne de la table jointe par la méthode "jointures" de Active Record -Comment utiliser la méthode "distincte" pour acquérir de manière unique des enregistrements en double
・ Tutoriel Rails https://railstutorial.jp/ ・ Guide des rails Association of Active Record https://railsguides.jp/association_basics.html ・ [Rails] Comment vérifier le contenu de la base de données [Cloud9] https://shuheitakada.com/rails-database-check -Afficher le nom de la colonne comme en-tête lors de l'affichage du résultat de l'instruction SELECT (commande .headers) https://www.dbonline.jp/sqlite/sqlite_command/index5.html ・ À propos de la méthode distincte de Rails https://qiita.com/toda-axiaworks/items/ad5a0e2322ac6a2ea0f4
Suivez le didacticiel Rails 6e édition ・ Utilisez cloud9 ・ Rubis 2.6.3p62 ・ Rails 6.0.3
Tutoriel Rails Chapitre 14 14.3.3 L'exercice de sous-sélection 3 provoque un bogue. Le but de l'exercice est d'utiliser la méthode des jointures pour afficher les micro-messages associés aux utilisateurs suivants et eux-mêmes sous forme de flux. Ça a l'air bien à première vue,
Lorsque vous publiez un micro post,
C'est trop de plaisir quoi qu'il arrive. Recherchez la cause tout en supprimant le sentiment de ne pas profiter clairement.
L'association de chaque modèle est la suivante.
python
class User < ApplicationRecord
has_many :microposts
has_many :passive_relationships, class_name: "Relationship", foreign_key: "followed_id"
has_many :followers, through: :passive_relationships, source: :follower
end
class Relationship < ApplicationRecord
belongs_to :follower, class_name: "User"
end
class Micropost < ApplicationRecord
belongs_to :user
end
# Copyright (c) 2016 Michael Hartl
La structure de chaque table est la suivante.
models/user.rb
def feed
part_of_feed = "relationships.follower_id = :id or microposts.user_id = :id"
Micropost.joins(user: :followers).where(part_of_feed, { id: id })
end
# Copyright (c) 2016 Michael Hartl
Tout d'abord, allez dans la console et vérifiez les instructions SQL créées par Rails.
rails_console
>>user.feed
SELECT * FROM "microposts" INNER JOIN "users" ON "users"."id" = "microposts"."user_id"
INNER JOIN "relationships" ON "relationships"."followed_id" = "users"."id"
INNER JOIN "users" "followers_users" ON "followers_users"."id" = "relationships"."follower_id"
WHERE (relationships.follower_id = 1 or microposts.user_id = 1)
ORDER BY "microposts"."created_at" DESC;
Ensuite, vérifiez la structure et les données de la table créée par la méthode de jointure sur la console de base de données.
rails_dbconsole
#Afficher le nom de la colonne dans le résultat de SELECT
>>.header on
>>SELECT * FROM "microposts" INNER
JOIN "users" ON "users"."id" = "microposts"."user_id"
INNER JOIN "relationships" ON "relationships"."followed_id" = "users"."id"
INNER JOIN "users" "followers_users" ON "followers_users"."id" = "relationships"."follower_id"
WHERE (relationships.follower_id = 1 or microposts.user_id = 1)
ORDER BY "microposts"."created_at" DESC LIMIT 5;
#Résultats de recherche|~|Signifie omettre des colonnes
id|content|user_id|~|id|name|~|id|follower_id|followed_id|~|id|name|~|
308|Enjoy Coding !!|1|~|1|Example User|~|50|4|1|~|4|Mr. Rey Lemke|~|
308|Enjoy Coding !!|1|~|1|Example User|~|51|5|1|~|5|Dr. Louisa Price|~|
308|Enjoy Coding !!|1|~|1|Example User|~|52|6|1|~|6|Charisse Stamm|~|
308|Enjoy Coding !!|1|~|1|Example User|~|53|7|1|~|7|Sang Metz IV|~|
308|Enjoy Coding !!|1|~|1|Example User|~|54|8|1|~|8|Robt Hamill|~|
Apparemment, follower_id provoque une duplication dans Microposts. À propos, parce que le nombre de doublons de Micropost et le nombre de ses propres abonnés correspondent, On peut en déduire que les abonnés sont la cause de la duplication.
En d'autres termes, dans le cas d'une relation de suivi comme celle ci-dessous id: 1 Tanaka → id: 2 Suzuki id: 2 Suzuki → id: 1 Tanaka id: 3 Sato → id: 1 Tanaka id: 3 Sato → id: 2 Suzuki Un tableau comme celui illustré ci-dessous est créé. Par Micopost.where, le cadre vert et la partie cadre rouge sont extraits, et la partie cadre rouge est doublée.
models/user.rb
#Partie de cadre vert
relationships.follower_id = :id:
#Partie de cadre rouge
microposts.user_id = :id
J'ai passé beaucoup de temps à essayer de comprendre la cause, mais une fois que j'ai trouvé la solution, je pouvais la résoudre en un seul mot.
Afin d'obtenir des enregistrements uniques sans duplication, la méthode "distincte" sera utilisée.
J'essaierai de l'intégrer immédiatement.
models/user.rb
def feed
part_of_feed = "relationships.follower_id = :id or microposts.user_id = :id"
Micropost.joins(user: :followers).where(part_of_feed, { id: id }).distinct
end
#Copyright (c) 2016 Michael Hartl
OK!!
Il est maintenant temps d'écrire un test. Donc, testez qu'il n'y a pas de micro-messages en double que j'ai publiés sur Feed.
test/integrationtest/microposts_interface_test.rb
def setup
@user = users(:michael)
end
test "should feed have microposts with uniqueness" do
log_in_as(@user)
get root_path
#Publier un micro post
content = "This micropost is only one!"
post microposts_path, params: { micropost: { content: content }}
follow_redirect!
#Confirmation de la duplication du flux
assert_select 'span.content', { :count=>1, :text=> "#{content}" }
end
#Copyright (c) 2016 Michael Hartl
Recommended Posts