PostRevisor kann Beiträge in gelöschten Themen nicht überarbeiten

tl;dr

Beim Aufruf von PostRevisor für einige Beiträge wird post_id auf nil gesetzt. Bin ich verrückt?

Antwort: Nein. PostRevisor greift auf post.topic zu, was für einen Beitrag in einem gelöschten Thema nil ist. Und dann setzt es post.topic auf nil, was wiederum post.topic_id auf nil setzt.

Ich denke, PostRevisor sollte das Thema so abrufen:

  @topic = topic || Topic.with_deleted.find_by(id: post_topic_id)

anstatt so:

  @topic = topic
post=Post.find_by(topic_id: 179227, post_number: 12)
post.topic_id => 179227
pr=PostRevisor.new(post)
post.topic_id => nil

Die ganze Geschichte

Ich arbeite an einem Skript, das goo.gl-Links repariert (der Dienst wird bald eingestellt, daher findet das Skript goo.gl-Links, ruft ab, wohin sie weitergeleitet werden, und ersetzt die goo.gl-URL durch diejenige, zu der sie weitergeleitet werden. Es funktioniert größtenteils.

Aber

Bei einigen Beiträgen scheint alles gut zu laufen, aber dann schlägt PostRevisor fehl, weil post.acting_user nil ist. Und dann, in meiner Ausnahmebehandlung, scheint es, dass topic_id nil ist, aber es ist nicht der post, der nil ist, da er immer noch eine post_number hat.

      begin
        puts "Revising (#{count}/#{total_posts}) https://mysite.com/t/#{post.topic_id}/#{post.post_number}"
        puts "missing topic_id for post #{post.id}" if !post.topic_id
        next if !post.topic_id
        PostRevisor.new(post).revise!(system_user, raw: new_raw, **revision_options)
      rescue => e
        puts "cannot revise (number: #{count} https://tw.forumosa.com/t/#{post.topic_id}/#{post.post_number}): #{e}"
      end
FIXING!!: https://goo.gl/maps/XaNG
B7qaZGzhBmM78 -----> https://www.google.com/maps/place/%E6%AD%A5%E9%81%93%E5%92%96%E5%95%A1%E9%A4%A8Cafe+Strada/@22.6300414,120.3153591,17z/data=!3m1!4b1!4m5!3m4!1s0x346e04944a9b3471:0x520c1f01c3d62e57!8m2!3d22.6301115!4d120.3175543?shorturl=1
Revising (680/1773) https://mysite.com/t/207069/1817
cannot revise (number: 680 https://mysite.com/t//1817): undefined method `acting_user=' for nil

Bei den allermeisten Beiträgen funktioniert dies einwandfrei, aber bei einer Teilmenge davon schlägt es fehl. Und wenn ich den Code Zeile für Zeile von Hand ausführe, erhalte ich dasselbe Ergebnis. Es scheint jedoch, dass, wenn ich pr=PostRevisor.new(post) mache, ich sehe, dass der Beitrag im pr-Datensatz keine topic_id hat und dann, wenn ich den post inspiziere, hat er jetzt topic_id auf nil gesetzt.

1 „Gefällt mir“

Interessenshalber, gibt es einen Grund, warum Sie das Post-Modell nicht direkt bearbeiten?

Denn wenn Sie 3000 Beiträge mit gsub und einem komplizierten Regex mit einer Reihe von Sonderfällen ändern (Korrektur: goo.gl, http://goo.gl, https://goo.gl, aber nicht https://maps.app.goo.gl oder https://map.goo.gl berühren, und vielleicht werden Sie von goo.gl rate-limited, und so weiter) möchten Sie vielleicht den Beitrag zurückbekommen, bevor Sie ihn total vermasselt haben!

Es war sehr cool, die Bearbeitungen ansehen zu können und das Vorher und Nachher zu sehen und die Möglichkeit zu haben, rückgängig zu machen! Eine Version würde zum Beispiel https://maps.app.goo.gl/abd12 in etwas wie https://maps.app.https://maps.google.com/;lkajw3rpoazse;flknmase;faijserfasefklasdfa ändern.

1 „Gefällt mir“

Das ergibt Sinn :slight_smile:

1 „Gefällt mir“

Vor einigen Jahren gab es ein ähnliches Skript, das ich CDCK für einen Kunden ausführen lassen wollte, und sie sagten (in meinen Worten, nicht in ihren): „Alter. Glaubst du, wir werden deinen Code ausführen, der einfach so eine Zillion Beiträge ändert und es keine Möglichkeit gibt, es rückgängig zu machen? Denk nochmal nach.“

1 „Gefällt mir“

Ja, ein anderer Ansatz ist, es auf einem Backup in einem kontrollierten Bereich auszuführen. Aber ich liebe Ihre Lösung.

1 „Gefällt mir“

Hier ist der Initialisierer:

Es ist also irgendwie so, dass der Beitrag dorthin gelangt und obwohl post_id einen Wert hat, post keinen hat?

Das kann ich nicht reproduzieren.
Der letzte post.topic_id ist nicht nil und wie erwartet eine Wiederholung des vorherigen Ergebnisses.

Ja. Es hat bei den meisten Beiträgen funktioniert. Bei einigen gibt es ein Problem.

[63] pry(main)> post.topic_id
=> 179227
[64] pry(main)> post.topic
=> nil
[65] pry(main)>

Ich bin ziemlich sicher, dass das nicht passieren soll. :person_shrugging:

Aber warte:

 Topic.find(post.topic_id)
ActiveRecord::RecordNotFound: Konnte Topic mit 'id'=179227 nicht finden [WO "topics"."deleted_at" IST NULL]
from /var/www/discourse/vendor/bundle/ruby/3.3.0/gems/activerecord-7.2.2.1/lib/active_record/relation/finder_methods.rb:428:in `raise_record_not_found_exception!'

Das Thema wurde gelöscht.

Die Frage ist also, ob es ein Fehler ist, dass man Beiträge in gelöschten Themen nicht überarbeiten kann.

Ich werde mich wahrscheinlich nicht darum kümmern und mein Skript post.topic auf nil prüfen lassen, anstatt post.topic_id.

1 „Gefällt mir“

Ja, da gibt es eine böse Integritätsverletzung mit dem Fremdschlüssel!

Ich glaube, einige der Schutzvorrichtungen (hüstel) sind abgeschaltet, weil die Tabellen normalerweise zu groß sind.

Vielleicht hat jemand ein topic.delete und kein destroy ausgeführt. Ups.

Meine Suche nach den Beiträgen war so etwas wie Post.where("raw like '%goo.gl%'"), und das gibt Beiträge in gelöschten Themen zurück. Und dann haben diese Beiträge eine topic_id, aber kein Thema. Ich glaube, es gibt eine Möglichkeit, dass Topic.find gelöschte Themen zurückgibt (weil ein Administrator diese Themen sehen kann, weshalb ich so verwirrt war. Dieser kleine Papierkorb ist leicht zu übersehen.)

Das ist also so:

deleted_topic = Topic.with_deleted.find_by(id: 123)

Vielleicht hätte ich das tun und den Beitrag aktualisieren sollen, bevor ich den PostRevisor aufrufe?

Aber in der Benutzeroberfläche kann ich einen Beitrag in einem gelöschten Thema aktualisieren, also denke ich, dass

def initialize(post, topic = post.topic)
  @post = post
  @topic = topic
  # Stellen Sie sicher, dass wir nur eine Topic-Instanz haben
  post.topic = topic
end

sollte sein

def initialize(post, topic = post.topic)
  @post = post
  @topic = topic || Topic.with_deleted.find_by(id: post_topic_id)
  # Stellen Sie sicher, dass wir nur eine Topic-Instanz haben
  post.topic = topic
end

Ich werde das zu Bug verschieben, falls jemand anderes das auch für einen Fehler hält.

Aber das funktioniert:

        if !post.topic # Beiträge in gelöschten Themen haben kein Thema und brechen PostRevisor
           post.topic = Topic.with_deleted.find_by(id: post.topic_id)
           next if !post.topic
        end
        PostRevisor.new(post).revise!(system_user, raw: new_raw, **revision_options)

Es gab Beiträge in 3 Themen, die Rails zum Absturz brachten. Ich gebe das auf. :slight_smile:

1 „Gefällt mir“

Und eine weitere Version des obigen Codes, die deleted_topic = Topic.with_deleted.find_by(id: 123) verwendet, um post.topic zu aktualisieren, funktioniert ebenfalls.

Es scheint jedoch immer noch ein Fehler zu sein. Oder vielleicht ist es kein Fehler, da Core etwas anderes verwaltet.

1 „Gefällt mir“

Oder ein fehlendes Feature (und damit eine fehlende Spezifikation)?

Online wird dies für Beiträge in gelöschten Themen niemals aufgerufen?

Ich stimme jedoch zu, dass es dies ordnungsgemäß verwalten sollte :thinking:

Vielleicht

Sie tun eindeutig etwas, um es für Beiträge in gelöschten Themen zu ermöglichen, wahrscheinlich so, wie ich es tue.

Ja. Jemand, der solche Entscheidungen trifft, kann dies bei Bedarf zurück in Dev verschieben.

Dieses Thema wurde 30 Tage nach der letzten Antwort automatisch geschlossen. Neue Antworten sind nicht mehr zulässig.