[RUBY] [Rails] Ruft einen eindeutigen Datensatz aus der Tabelle ab, die durch die Join-Methode von Active Record verknüpft wird (Rails-Lernprogramm, Kapitel 14).

Einführung

Ich bin auf einen Fehler gestoßen, der im Material nicht erwähnt wurde, als ich ihn in das Rails-Tutorial aufgenommen habe. Untersuchen Sie die Ursache des Fehlers und fassen Sie die Lösung zusammen.

Was Sie in diesem Artikel sehen können

Referenzmaterial

・ Rails-Tutorial  https://railstutorial.jp/ ・ Rails Guide Association of Active Record  https://railsguides.jp/association_basics.html ・ [Rails] So überprüfen Sie den Inhalt der Datenbank [Cloud9]  https://shuheitakada.com/rails-database-check

Über die Umwelt

Folgen Sie dem Rails Tutorial 6. Ausgabe ・ Verwenden Sie cloud9 ・ Ruby 2.6.3p62 ・ Schienen 6.0.3

Lernmotiv

Rails Tutorial Kapitel 14 14.3.3 Unterauswahl Übung 3 verursacht einen Fehler. Der Zweck dieser Übung besteht darin, die Joins-Methode zu verwenden, um die Mikroposts anzuzeigen, die den folgenden Benutzern und sich selbst als Feed zugeordnet sind. Es sieht auf den ersten Blick gut aus, image.png

Wenn Sie einen Mikropost posten, image.png

Es ist zu viel Freude, egal was passiert. Untersuchen Sie die Ursache, während Sie das Gefühl unterdrücken, nicht klar zu genießen.

Modellassoziation

Die Zuordnung jedes Modells ist wie folgt.

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

Die Struktur jeder Tabelle ist wie folgt. Rails Tutorial14章joinsの関連図.png

Der Code, der es verursacht hat

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

Gehen Sie zunächst in die Konsole und überprüfen Sie die von Rails erstellten SQL-Anweisungen.

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;

Überprüfen Sie als Nächstes die Struktur und die Daten der Tabelle, die mit der Join-Methode in der Datenbankkonsole erstellt wurden.

rails_dbconsole


#Zeigen Sie den Spaltennamen im Ergebnis von SELECT an
>>.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;

#Suchergebnisse|~|Bedeutet, dass Spalten weggelassen werden
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|~|

Anscheinend verursacht follower_id eine Verdoppelung in Microposts. Übrigens, weil die Anzahl der Duplikate von Micropost und die Anzahl der eigenen Follower übereinstimmen, Es kann gefolgert werden, dass Follower die Ursache für die Duplizierung sind.

Mit anderen Worten, im Fall einer Folgebeziehung wie der folgenden ID: 1 Tanaka → ID: 2 Suzuki ID: 2 Suzuki → ID: 1 Tanaka ID: 3 Sato → ID: 1 Tanaka ID: 3 Sato → ID: 2 Suzuki Eine Tabelle wie die unten gezeigte wird erstellt. Mit Micopost.where werden der grüne Rahmen und der rote Rahmenteil extrahiert und der rote Rahmenteil verdoppelt. RailsTuorial14章Joinsで作成されるテーブルの模式図.png

models/user.rb


 #Grüner Rahmenteil
 relationships.follower_id = :id: 

 #Roter Rahmenteil
 microposts.user_id = :id

Lösung

Ich habe lange gebraucht, um die Ursache herauszufinden, aber sobald ich die Lösung herausgefunden hatte, konnte ich sie in nur einem Wort lösen.

Verwenden Sie die unterschiedliche Methode

Um einen eindeutigen Datensatz ohne Duplizierung zu erhalten, wird die "eindeutige" Methode verwendet.

Ich werde versuchen, es sofort zu integrieren.

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

image.png OK!!

Schreiben Sie einen Test

Jetzt ist die Zeit, einen Test zu schreiben. Testen Sie also, ob es keine doppelten Mikroposts gibt, die ich im Feed gepostet habe.

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

   #Posten eines Mikroposts
   content = "This micropost is only one!"
   post microposts_path, params: { micropost: { content: content }}
   follow_redirect!

   #Bestätigung der Feed-Duplizierung
   assert_select 'span.content', { :count=>1, :text=> "#{content}" }
 end

#Copyright (c) 2016 Michael Hartl

Recommended Posts

[Rails] Ruft einen eindeutigen Datensatz aus der Tabelle ab, die durch die Join-Methode von Active Record verknüpft wird (Rails-Lernprogramm, Kapitel 14).
So erstellen Sie eine eindeutige Datenkombination in der Schienen-Zwischentabelle
Eine Überprüfung des von Rails-Anfängern verwendeten Codes
[Rails] Lassen Sie uns den Schwellenwert für die "Längenprüfung" der Modellvalidierung dynamisch aus Tabelleninformationen abrufen
Eine Aufzeichnung über das Studium des Spring Framework von Grund auf neu
[Rails Tutorial Kapitel 5] Erstellen Sie ein Layout
Eine Reihe von Ablauf der Tabellenerstellung → Datensatzerstellung, Löschung → Tabellenlöschung in Ruby on Rails
Finden Sie den Unterschied von einem Vielfachen von 10
Zerlegen Sie die Installation von "$ printf": --no-document \ nupdate: --no-document \ n ">> ~ / .gemrc" in Kapitel 1 des Rails-Lernprogramms
Benennen und rufen Sie in Ruby übergeordnete Klassenmethoden explizit auf
Ruft den Klassennamen und den Methodennamen des Controllers ab, der vom HandlerInterceptor von Spring Boot ausgeführt wird