مرحباً،
أنا أتطلع إلى تغيير ملكية جميع المشاركات الافتتاحية في مواضيع الأحداث التي تحمل وسم “ethan” بحيث يتغير المالك من “system” إلى المستخدم “Ethan_Hoom1”. أنا أدير نسخة مستضافة ذاتياً ولدي وصول إلى Rails console.
بعد مراجعة التوصيات في العمليات الإدارية المجمعة و تغيير ملكية جميع المشاركات لمستخدم معين، أعددت البرنامج النصي التالي. سأكون ممتناً لأي اقتراحات أو أفضل الممارسات قبل تشغيله في بيئة الإنتاج:
# ابحث عن كائن الوسم بالاسم "ethan"
tag = Tag.find_by(name: "ethan")
# توقف فوراً إذا لم يتم العثور على الوسم
raise "Tag not found" unless tag
# ابحث عن المستخدم الذي سيصبح المالك الجديد للمشاركات
# username_lower أكثر أماناً من username (غير حساس لحالة الأحرف)
new_owner = User.find_by(username_lower: "ethan_hoom1")
# توقف فوراً إذا لم يتم العثور على المستخدم الهدف
raise "New owner user not found" unless new_owner
# ابحث عن حساب المستخدم system
# استخدم Discourse.system_user كخيار احتياطي في حال فشل البحث عن السجل
system_user = User.find_by(username_lower: "system") || Discourse.system_user
# توقف فوراً إذا لم يتم العثور على المستخدم system
raise "System user not found" unless system_user
# عندما تكون القيمة true، سيقوم البرنامج النصي بطباعة ما سيتم تغييره فقط
# ولن يقوم بإجراء أي تعديلات في قاعدة البيانات
DRY_RUN = true
# حد أمان اختياري للتشغيل الأول (على سبيل المثال 10 أو 50)
# اضبطها على nil لمعالجة جميع المشاركات المطابقة
LIMIT = nil
# بناء استعلام ActiveRecord للمشاركات التي نريد تعديلها
scope = Post
# ربط المشاركات ← المواضيع ← وسم_الموضوعات حتى نتمكن من التصفية حسب الوسم
.joins(topic: :topic_tags)
# استهداف المشاركة الافتتاحية في كل موضوع فقط
.where(post_number: 1)
# استهداف المشاركات المملوكة حالياً للمستخدم system فقط
.where(user_id: system_user.id)
# تضمين المواضيع التي تحمل وسم "ethan" فقط
.where(topic_tags: { tag_id: tag.id })
# استبعاد الرسائل الخاصة والمواضيع المحذوفة
.where(topics: {
archetype: Archetype.default,
deleted_at: nil
})
# إذا تم تعيين LIMIT، قم بتقييد عدد المشاركات التي تتم معالجتها
scope = scope.limit(LIMIT) if LIMIT
# التكرار عبر المشاركات المطابقة على دفعات لتجنب مشاكل الذاكرة
scope.find_each(batch_size: 100) do |first_post|
# تخزين معرف الموضوع للإخراج المسجل
topic_id = first_post.topic_id
# إذا كان وضع التشغيل الجاف ممكناً، فلا تقم بإجراء أي تعديلات
if DRY_RUN
puts "[DRY RUN] Would change owner for topic #{topic_id} (post #{first_post.id})"
next
end
begin
# استخدام خدمة تغيير مالك المشاركة الرسمية لـ Discourse
PostOwnerChanger.new(
# تغيير ملكية المشاركة الافتتاحية فقط
post_ids: [first_post.id],
# الموضوع الذي يحتوي على المشاركة
topic_id: topic_id,
# المستخدم الذي سيصبح المالك الجديد
new_owner: new_owner,
# المستخدم الذي يقوم بالإجراء (المستخدم system)
acting_user: system_user,
# لا تقم بإنشاء مراجعة تحرير لهذا التغيير
skip_revision: true
).change_owner!
# تسجيل النجاح في وحدة التحكم
puts "Changed owner for topic #{topic_id} (post #{first_post.id})"
rescue => e
# إذا فشل أي شيء، سجل الخطأ ولكن استمر في معالجة العناصر الأخرى
puts "FAILED topic #{topic_id} (post #{first_post.id}): #{e.class}: #{e.message}"
end
end
أسئلة:
- هل هناك أي محاذير أو حالات حافة يجب أن أكون على دراية بها بخصوص
PostOwnerChangerلهذا الاستخدام؟ - هل من المستحسن تحديث حقل
topic.userأيضاً كما هو موضح في السطر الاختياري؟ - هل لديك أي توصيات لمزيد من التحسينات المتعلقة بالسلامة أو الأداء فيما يتعلق بهذه العملية المجمعة؟
شكراً لمساعدتكم ولكل الوثائق الرائعة!