Ich habe eine Antwortfunktion für die Rails Tutorial-Erweiterung (Teil 2) erstellt: Modell ändern

Dies ist eine Fortsetzung des vorherigen Artikels zum Erstellen einer Antwortfunktion in Kapitel 14 des Rails-Lernprogramms.

Identifizieren Sie, was in der Codierungsarbeit zu tun ist

Ich werde die zu erledigende Arbeit überprüfen und auswaschen. ・ Machen Sie einen Zweig mit Git ・ Test durchführen    model、integration

Spalte zum Modell hinzufügen

Suchen Sie nach Text zum Hinzufügen einer Modellspalte. Sie können sehen, dass Sie in 9.1.1 Spalten mit Migration hinzugefügt haben.

Überlegen Sie, wie Sie die Anzeige durch Antwort im Modell erstellen können. Schauen wir uns die Spezifikationen noch einmal an. @reply sollte nur im Feed des Empfängers und im Feed des Absenders erscheinen. Denken Sie in drei Teilen darüber nach, je nachdem, wer es anzeigt. 1 Absender, 2 Empfänger, 3. Dritter (weder Absender noch Empfänger)

1 Absender

Da es sich um einen von mir geposteten Mikropost handelt, wird er auch mit der aktuellen Funktion angezeigt.

2 Empfänger

Es gibt zwei Möglichkeiten: Der Empfänger folgt dem Absender und der Empfänger nicht. Wenn der Empfänger dem Absender folgt, ist er in der aktuellen Funktion weiterhin sichtbar. Wenn der Empfänger dem Absender nicht folgt, wird er mit der aktuellen Funktion nicht angezeigt. Sie können sehen, dass wir hier Funktionen hinzufügen müssen.

Die Funktion besteht darin, in_reply_to anzuzeigen, wenn Sie gleich sind. Ich dachte, ich würde die Methode user.micrposts ändern, aber sie funktioniert nicht. Ich habe es nicht gepostet. Der Absender wird nicht ausgewählt und der Mikropost der Person wird nicht zurückgegeben. Egal wer gepostet hat Es ist eine Funktion, um alle Mikroposts anzuzeigen, die gleich in_reply_to sind.

Die Idee ist, dass das Risiko von Leistungsproblemen umso höher ist, je mehr Mikroposts Sie haben. Es scheint notwendig, einen Index als Gegenmaßnahme hinzuzufügen. Ich verstehe, dass es ein Risiko ist, nach einem alternativen Schlüssel zu suchen, anstatt nach einem Primärschlüssel.

Diese Implementierungsmethode zeigt an, wie Sie es erstellen, unabhängig davon, ob Sie dem Absender folgen. Daher habe ich festgestellt, dass es nicht erforderlich ist, die Fälle zu trennen.

Überlegen Sie sich als Nächstes, zu welcher Methode die Funktion hinzugefügt werden soll. In Listing 14.46 sieht die Feed-Methode im Benutzermodell gut aus. Es scheint, dass Sie die Bedingung mit where angeben können.

3 Dritte

Wenn ein Dritter den Feed-Bildschirm des Empfängers anzeigt, wird die Antwort nicht angezeigt. Wenn Sie eine Funktion mit den oben genannten Spezifikationen erstellen, wird diese angezeigt. Daher muss eine Funktion hinzugefügt werden, die nicht angezeigt wird. Wenn Sie nicht gleich in_reply_to sind, können Sie es ausblenden. Zuerst dachte ich, ich sollte Änderungen an der Rückgabe der user.micrposts-Methode vornehmen. Wie ich oben erwähnt habe, fand ich die Fütterungsmethode beim Empfänger gut, so dass ich intuitiv der Meinung war, dass dieselbe Methode gut ist.

Bedingte SELECT-Anweisung

Lesen Sie noch einmal 14.3.2.

Wählen Sie in der Mikroposttabelle alle Mikroposts aus, deren ID dem Benutzer entspricht, dem ein Benutzer (dh er selbst) folgt.

Wählen Sie in der Mikroposttabelle alle Antworten aus, deren Empfänger Sie sind.

SELECT * FROM microposts
WHERE  user_id IN (<list of ids>) 
             OR user_id = <user id> 
             OR in_reply_to = <user id>

Ich denke, es sollte getan werden.

Listing 14.44

  def feed
    Micropost.where("user_id IN (?) OR user_id = ? OR in_reply_to = ?", following_ids, id,id)
  end

Sieht gut aus.

Ich urteile, dass die Spezifikationen damit unterdrückt wurden, und entscheide mich, es zu machen.

Erstellen Sie eine Verzweigung

Erstellen Sie wie gewohnt einen Zweig.

ubuntu:~/environment/sample_app (master) $ git checkout -b reply-micropost

Spalte zum Modell hinzufügen

Im Text erfahren Sie, wie Sie dem Modell Spalten hinzufügen. 6.3.1 Ich habe eine Spalte mit "Hashed Password" hinzugefügt. Mach es auf die gleiche Weise.

ubuntu:~/environment/sample_app (reply-micropost) $ rails generate migration add_reply_to_microposts in_reply_to:integer

db/migrate/20201003003147_add_reply_to_microposts.rb


class AddReplyToMicroposts < ActiveRecord::Migration[5.1]
  def change
    add_column :microposts, :in_reply_to, :integer
  end
end

Erstellen Sie einen Modelltest

Erstellen Sie als Nächstes einen Modelltest. 13.1.2 Gehen Sie genauso vor wie bei der Micropost-Validierung. Was das zu testende Modell betrifft, habe ich dem Mikropost eine Spalte hinzugefügt, daher denke ich, dass es Mikropost ist.

Erstellen Sie einen Antwort-Mikropost basierend auf dem Absender und dem Empfänger der Antwort.

Wenn Sie antworten, ist der auf dem Feed-Bildschirm angezeigte Test der Integrationstest. Überlegen Sie sich vorher, was Sie mit dem Modelltest testen möchten.

Als Test für die Funktion der durch Antwort hinzugefügten Methode scheint das Aktualisieren und Löschen nicht in CRUD enthalten zu sein. Sie müssen daher eine Antwort erstellen und lesen. Ich werde es auf der Konsole versuchen.

>> user2.microposts.create!(content: "test2", in_reply_to: 1 )
>> user2.microposts.create!(content: "test3", in_reply_to: 1 )                                                                                 

>> Micropost.where(in_reply_to: 1)                                                                                 
  Micropost Load (0.2ms)  SELECT  "microposts".* FROM "microposts" WHERE "microposts"."in_reply_to" = ? ORDER BY "microposts"."created_at" DESC LIMIT ?  [["in_reply_to", 1], ["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<Micropost id: 304, content: "test3", user_id: 30, created_at: "2020-10-03 02:37:38", updated_at: "2020-10-03 02:37:38", picture: nil, in_reply_to: 1>, #<Micropost id: 303, content: "test2", user_id: 30, created_at: "2020-10-03 02:18:35", updated_at: "2020-10-03 02:18:35", picture: nil, in_reply_to: 1>]>

Wenn die vorhandene Methode ausreicht, scheint das Testen nicht erforderlich zu sein, da das Modell keine Funktionen hinzufügt, aber ich werde es vorerst schreiben.

test/models/micropost_test.rb


  test "reply should be returned" do
    @reply_post = @reply_sender.microposts.create!(content: "reply test1", in_reply_to: @user.id)
    assert Micropost.where(in_reply_to: @user.id).include?(@reply_post)
  end

Integrationstest erstellen

Nachdem wir das Modell getestet haben, erstellen wir einen Integrationstest. Der Inhalt des Tests besteht darin, eine Antwort zu erstellen und diese auf dem Feed-Bildschirm des Empfängers anzuzeigen.

Überlegen Sie sich vorher, wo Sie die Änderungen vornehmen sollen. Ich dachte, ich müsste das Ergebnis testen, da ich Änderungen am Controller vornehmen würde.

Beginnen wir mit dem Integrationstest. Auf der Suche nach einem Test, der hilfreich zu sein scheint, sieht follow_test.rb gut aus. Außerdem wird der zu postende Ort basierend auf microposts_interface_test.rb kopiert.

test/integration/reply_test.rb  RED


  test "reply to user " do   
    log_in_as(@user)
    content = "@reply #{@other.name} Cum aspermatur"
    post microposts_path, params: { micropost: {content: content }}
    log_in_as(@other)
    get root_path
    assert_not @other.following?(@user)
    #get root_path
    assert_match content, response.body
    #assert_match content, response.body
  end

Vorschub wechseln

Nehmen Sie Änderungen am Feed vor, um eine Antwort anzuzeigen.

Erstellen Sie zunächst Testdaten. Fügen Sie dem Gerät Daten hinzu.

test/fixtures/microposts.yml


tonton:
  content: "@reply malory tonton is the name of the panda."
  created_at: <%= Time.zone.now %>
  user: michael

Wo soll der Feed getestet werden, aber ich denke, es ist ein Modelltest, da er sich zum Benutzermodell ändert.

test/models/user_test.rb RED


 test "feed should have the reply posts" do
    michael = users(:michael)
    malory = users(:malory)
    reply_post = microposts(:tonton)
    assert michael.feed.include?(reply_post)
    assert malory.feed.include?(reply_post)
    puts reply_post.content
  end
end

Ändern Sie den Feed.

app/models/user.rb


  def feed
    following_ids = "SELECT followed_id FROM relationships 
                     WHERE follower_id = :user_id"
    Micropost.where("user_id IN (#{following_ids})
                     OR user_id = :user_id
                     OR in_reply_to = reply_id",
                     user_id: id, 
                     reply_id: id )
  end
tonton:
  content: "@reply malory tonton is the name of the panda."
  created_at: <%= Time.zone.now %>
  user: michael
  in_reply_to: <%= User.find_by(name: "Malory Archer").id %>

Andere Tests schlagen aufgrund eines Futterwechsels fehl

Das Ändern des Feeds führte dazu, dass andere Tests fehlschlugen. Siehe die Fehlermeldung.

ubuntu:~/environment/sample_app (reply-micropost) $ rails test test/models/micropost_test.rb 
Running via Spring preloader in process 2886
Started with run options --seed 405

 FAIL["test_order_should_be_most_recent_first", MicropostTest, 0.5243559590000189]
 test_order_should_be_most_recent_first#MicropostTest (0.52s)
        --- expected
        +++ actual
        @@ -1 +1 @@
        -#<Micropost id: 941832919, content: "Writing a short test", user_id: 762146111, created_at: "2020-10-10 01:35:16", updated_at: "2020-10-10 01:35:17", picture: nil, in_reply_to: nil>
        +#<Micropost id: 981300582, content: "@reply malory tonton is the name of the panda.", user_id: 762146111, created_at: "2020-10-10 01:35:17", updated_at: "2020-10-10 01:35:17", picture: nil, in_reply_to: 659682706>
        test/models/micropost_test.rb:33:in `block in <class:MicropostTest>'

  6/6: [===================================================================================================] 100% Time: 00:00:00, Time: 00:00:00

Ich erhalte die Fehlermeldung, dass ein Problem mit den Testdaten vorliegt. Ich denke, dass die Ursache darin besteht, dass die Testdaten mit der letzten Buchungszeit als most_recent in fixture erstellt wurden, aber tonton hatte eine neuere Buchungszeit. Es ist nicht erforderlich, die Buchungszeit zu aktualisieren. Korrigieren Sie daher die Buchungszeit von tonton.

test/fixtures/microposts.yml vor der Änderung


tonton:
  content: "@reply malory tonton is the name of the panda."
  created_at: <%= Time.zone.now %>
  user: michael

test/fixtures/microposts.nach dem Ändern von yml


tonton:
  content: "@reply malory tonton is the name of the panda."
  created_at: <%= 2.minutes.ago %>
  user: michael
  in_reply_to: <%= User.find_by(name: "Malory Archer").id %>

Es wurde sicher repariert.

Anzeige und Bestätigung auf dem Bildschirm

Stellen Sie sicher, dass der Mikropost mit @reply auf der Seite angezeigt wird. Erstellen Sie Beispieldaten unter Listing 13.25: "Hinzufügen von Mikroposts zu Beispieldaten".

db/seeds.rb


# reply
sender   = users.first
reciever = users.second
reply_content = "@reply #{receiver.name} reply test"
sender.microposts.create!(content: reply_content, 
                          in_reply_to: receiver.id )

Als ich den Rails-Server anhob und den Bildschirm anzeigte, wurde bestätigt, dass der Antwort-Mikropost angezeigt wurde.

Benötigte Zeit

7,0 Stunden von 10/2 bis 10/10.

Recommended Posts

Ich habe eine Antwortfunktion für die Rails Tutorial-Erweiterung (Teil 2) erstellt: Modell ändern
Ich habe eine Antwortfunktion für die Rails Tutorial-Erweiterung (Teil 5) erstellt:
Ich habe eine Antwortfunktion für die Erweiterung Rails Tutorial (Teil 4) erstellt: Eine Funktion, die den Benutzer einzigartig macht
Ich habe versucht, eine Nachrichtenfunktion der Rails Tutorial-Erweiterung (Teil 1) zu erstellen: Erstellen Sie ein Modell
Ich habe versucht, eine Antwortfunktion für die Rails Tutorial-Erweiterung (Teil 3) zu erstellen: Ein Missverständnis der Spezifikationen wurde behoben
Ich habe versucht, eine Nachrichtenfunktion für die Erweiterung Rails Tutorial (Teil 2) zu erstellen: Erstellen Sie einen Bildschirm zum Anzeigen
Tutorial zum Erstellen eines Blogs mit Rails für Anfänger Teil 1
Tutorial zum Erstellen eines Blogs mit Rails für Anfänger Teil 2
Tutorial zum Erstellen eines Blogs mit Rails für Anfänger Teil 0
Ich habe eine einfache Empfehlungsfunktion erstellt.
Ich habe ein Diff-Tool für Java-Dateien erstellt
Ich habe eine Ruby-Erweiterungsbibliothek in C erstellt
Ich habe einen LINE Bot mit Rails + Heroku gemacht
Ich habe mit Ruby On Rails ein Portfolio erstellt
Ich habe eine Funktion zum Registrieren von Bildern bei der API in Spring Framework erstellt. Teil 1 (API Edition)
Ich habe ein Docker-Image für die japanische Version von SDAPS erstellt
Ich habe ein Check-Tool für das Release-Modul erstellt
Ich habe eine Methode entwickelt, um nach Premium Friday zu fragen
Ich möchte eine Funktion in der Rails Console definieren
Ich habe eine Bibliothek zum Anzeigen von Tutorials auf Android erstellt.
Ich habe eine Funktion zum Registrieren von Bildern bei der API in Spring Framework erstellt. Teil 2 (Client Edition)
Ich habe versucht, eine japanische Version der Automatik-Mail von Rails / devise zu erstellen
Ich habe eine Entwicklungsumgebung mit Rails6 + Docker + PostgreSQL + Materialise erstellt.
Ich möchte eine Produktinformationsbearbeitungsfunktion ~ part1 ~ implementieren
Ich habe einen Butler gemacht, der die Tweets zusammenfasst [Maximum Covering Model]
Ich habe eine Chat-App erstellt.
[Rails] Implementierung der Tutorial-Funktion
[Rails] Ich habe eine einfache Kalender-Mini-App mit benutzerdefinierten Spezifikationen erstellt.
Implementieren Sie eine verfeinerte Suchfunktion für mehrere Modelle ohne Rails5-Juwel.
Ich möchte eine Browsing-Funktion mit Ruby on Rails hinzufügen
Erstellt eine Methode zum Anfordern von Premium Friday (Java 8-Version)
Ich habe versucht, mit Rails eine Gruppenfunktion (Bulletin Board) zu erstellen