مشكلة في تنفيذ counter_cache
-
28-09-2019 - |
سؤال
أنا أحصل على إجهاض! ... posts_count تم وضع علامة على أخطاء readonly.
لدي نموذجان: المستخدم والنشر.
users has_many posts.
posts belongs_to :user, :counter_cache => true
لديّ ترحيل يضيف عمود posts_count إلى جدول المستخدمين ثم يحسب ويسجل العدد الحالي من المنشورات لكل مستخدم.
self.up
add_column :users, :posts_count, :integer, :default => 0
User.reset_column_information
User.all.each do |u|
u.update_attribute( :posts_count, u.posts.count)
end
end
عندما أقوم بتشغيل الترحيل أحصل على الخطأ. هذا واضح إلى حد ما ، بالطبع ، وإذا قمت بإزالة إعلان: counter_cache من نموذج المنشورات ، على سبيل المثال
belongs_to :user
الهجرة تعمل بشكل جيد. من الواضح أن هذا ليس منطقيًا لأنك لا تستطيع تنفيذها بهذه الطريقة حقًا. ماذا ينقصني؟
المحلول
يجب أن تستخدم User.reset_counters
لفعل هذا. بالإضافة إلى ذلك ، أوصي باستخدام find_each
بدلاً من each
لأنها ستكرر المجموعة على دفعات بدلاً من كل مرة.
self.up
add_column :users, :posts_count, :integer, :default => 0
User.reset_column_information
User.find_each do |u|
User.reset_counters u.id, :posts
end
end
نصائح أخرى
حسنًا ، تنص الوثائق على:
تتم إضافة أعمدة ذاكرة التخزين المؤقت المضادة إلى قائمة السمات القراءة فقط من خلال attr_readonly.
أعتقد أن هذا ما يحدث: أنت تعلن العداد في تعريف النموذج ، مما يجعل سمة "posts_count" للقراءة فقط. ثم ، في الترحيل ، تحاول تحديثه مباشرة ، مما يؤدي إلى الخطأ الذي ذكرته.
يتمثل الحل السريع في إزالة إعلان counter_cache من النموذج ، وتشغيل الترحيل (من أجل إضافة العمود المطلوب إلى قاعدة البيانات وملبئه مع تعدادات المنشور الحالية) ، ثم إعادة إضافة إعلان counter_cache إلى الموديل. يجب أن تعمل ولكنها سيئة وتتطلب تدخلًا يدويًا أثناء الهجرة - ليست فكرة جيدة.
وجدت منشور المدونة هذا وهو ما يشير إلى تغيير قائمة السمات القراءة فقط أثناء الترحيل ، فهي مغمورة بعض الشيء ولكن قد ترغب في تجربتها.