PostRevisor لا يمكنه مراجعة المشاركات في المواضيع المحذوفة

ملخص سريع

بالنسبة لبعض المشاركات، يؤدي استدعاء PostRevisor إلى تعيين post_id إلى nil. هل أنا مجنون؟

الإجابة: لا. يصل PostRevisor إلى post.topic، وهو nil لمشاركة في موضوع محذوف. ثم يقوم بتعيين post.topic إلى nil، والذي بدوره يعين post.topic_id إلى nil.

أعتقد أنه يجب على PostRevisor الحصول على الموضوع على النحو التالي:

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

بدلاً من ذلك:

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

القصة الكاملة

أنا أعمل على نص برمجي يقوم بإصلاح روابط goo.gl (الخدمة في طريقها إلى الإيقاف قريبًا، لذا يبحث النص البرمجي عن روابط goo.gl، ويجلب ما يتم إعادة توجيهها إليه ويستبدل عنوان URL الخاص بـ goo.gl بالعنوان الذي يتم توجيهه إليه. إنه يعمل في الغالب.

ولكن

بالنسبة لعدد من المشاركات، يبدو أن كل شيء يسير على ما يرام، ولكن بعد ذلك يفشل PostRevisor لأن post.acting_user هو nil. وبعد ذلك، في عملية الاسترداد الخاصة بي، يبدو أن topic_id هو nil، ولكن ليس post هو الذي يكون nil، لأنه لا يزال لديه post_number.

      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/d
ata=!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

بالنسبة لغالبية المشاركات، يعمل هذا بشكل جيد، ولكن بالنسبة لمجموعة فرعية منها، فإنه يفشل على هذا النحو. وإذا قمت بتشغيل الكود يدويًا سطرًا بسطر، أحصل على نفس الشيء. يبدو الأمر، على الرغم من ذلك، أنه إذا قمت بتنفيذ pr=PostRevisor.new(post)، أرى أن المشاركة في سجل pr ليس لديها topic_id وبعد ذلك إذا قمت بفحص post، فإنها تحتوي الآن على topic_id معين إلى nil.

إعجاب واحد (1)

من باب الفضول، هل هناك أي سبب لعدم قيامك بتعديل نموذج المنشور مباشرة؟

لأنه إذا كنت تقوم بتغيير 3000 منشور باستخدام gsub وتعبير نمطي معقد مع مجموعة من الحالات الطرفية (إصلاح: goo.gl، http://goo.gl، https://goo.gl، ولكن لا تلمس https://maps.app.goo.gl، أو https://map.goo.gl، وربما يتم تحديد معدل طلباتك بواسطة goo.gl، وهكذا) فقد ترغب في استعادة المنشور قبل أن تفسده تمامًا!

لقد كان من الرائع جدًا أن تكون قادرًا على النظر إلى التعديلات ورؤية قبل وبعد والقدرة على التراجع! سيؤدي أحد الإصدارات إلى تحويل https://maps.app.goo.gl/abd12 إلى شيء مثل https://maps.app.https://maps.google.com/;lkajw3rpoazse;flknmase;faijserfasefklasdfa، على سبيل المثال.

إعجاب واحد (1)

هذا منطقي :slight_smile:

إعجاب واحد (1)

منذ سنوات كان هناك نص برمجي مشابه حاولت تشغيله لعميل ما، وقالوا (بكلماتي الخاصة، وليس كلماتهم) “يا رجل. هل تعتقد أننا سنقوم بتشغيل الكود الخاص بك الذي يغير عددًا لا يحصى من المنشورات بهذه الطريقة العشوائية ولا توجد طريقة للتراجع عنها؟ فكر مرة أخرى.”

إعجاب واحد (1)

نعم، النهج الآخر هو تشغيله على نسخة احتياطية في منطقة خاضعة للرقابة. لكنني أحببت حلك.

إعجاب واحد (1)

إذًا، هذه هي المُهيئ:

إذًا، بطريقة ما يصل المنشور إلى هناك وعلى الرغم من أن post_id له قيمة، فإن post ليس كذلك؟

لا يمكنني تكرار هذا.

آخر post.topic_id ليس فارغًا وكما هو متوقع تكرار للنتيجة السابقة

نعم. لقد نجح الأمر مع معظم المشاركات. هناك شيء غريب مع بعضها.

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

أنا متأكد من أن هذا لا يفترض أن يحدث. :person_shrugging:

ولكن انتظر:

Topic.find(post.topic_id)
ActiveRecord::RecordNotFound: Couldn't find Topic with 'id'=179227 [WHERE "topics"."deleted_at" IS 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!'

تم حذف الموضوع.

إذن، السؤال هو ما إذا كان من المفترض ألا تتمكن من مراجعة المشاركات في المواضيع المحذوفة.

أعتقد أنني لن أهتم وسأجعل النص البرمجي الخاص بي يتحقق من post.topic مقابل nil بدلاً من post.topic_id.

إعجاب واحد (1)

نعم، هناك نقص كبير في السلامة هنا مع المفتاح الخارجي!
أعتقد أن بعض الضوابط (آه) معطلة لأن الجداول كبيرة جدًا عادةً.
ربما قام شخص ما بإجراء topic.delete وليس destroy. يا إلهي.

كان بحثي عن المشاركات مثل Post.where("raw like '%goo.gl%'")، وهذا سيعيد المشاركات في مواضيع محذوفة. وبعد ذلك، تحتوي هذه المشاركات على topic_id، ولكن ليس موضوعًا. أعتقد أن هناك طريقة لجعل Topic.find يعيد المواضيع المحذوفة (لأن المسؤول يمكنه رؤية تلك المواضيع، وهذا هو سبب ارتباكي الشديد. هذه السلة الصغيرة سهلة الفقدان.)

لذا، هذا يبدو كالتالي:

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

لذا ربما كان يجب أن أفعل ذلك وأحدّث المشاركة قبل استدعاء PostRevisor؟

ولكن في تجربة المستخدم يمكنني تحديث مشاركة في موضوع محذوف، لذا أفكر أن

def initialize(post, topic = post.topic)
  @post = post
  @topic = topic
  # Make sure we have only one Topic instance
  post.topic = topic
end

يجب أن يكون

def initialize(post, topic = post.topic)
  @post = post
  @topic = topic || Topic.with_deleted.find_by(id: post_topic_id)
  # Make sure we have only one Topic instance
  post.topic = topic
end

سأقوم بنقل هذا إلى Bug في حال اعتقد شخص آخر أنه كذلك.

ولكن هذا يعمل:

        if !post.topic # posts in delted topics have no topic and break 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)

كانت هناك مشاركات في 3 مواضيع تسببت في تعطل Rails. لقد استسلمت بشأن ذلك. :slight_smile:

إعجاب واحد (1)

وهناك إصدار آخر من ما سبق يقوم بتحديث post.topic باستخدام deleted_topic = Topic.with_deleted.find_by(id: 123) يعمل أيضًا.

لا يزال يبدو خطأً، على الرغم من ذلك. أو ربما نظرًا لأن النواة تقوم بشيء آخر لإدارة هذا، فهو ليس خطأً.

إعجاب واحد (1)

أو ميزة مفقودة (وبالتالي مواصفات)؟

عبر الإنترنت، لن يتم استدعاء هذا أبدًا للمنشورات في مواضيع محذوفة؟

أتفق، مع ذلك، على أنه يجب إدارتها بشكل صحيح :thinking:

ربما

من الواضح أنهم يفعلون شيئًا للسماح له بالعمل على المشاركات في المواضيع المحذوفة، ربما مثلما أفعل.

نعم. يمكن لشخص يتخذ مثل هذه القرارات نقل هذا مرة أخرى إلى Dev إذا اعتقد أن ذلك مناسب.

تم إغلاق هذا الموضوع تلقائيًا بعد 30 يومًا من آخر رد. لم يعد يُسمح بالردود الجديدة.