Rails :counter_cache لا يقوم بتشغيل رد الاتصال after_update
-
29-10-2019 - |
سؤال
لذلك، لدي نماذج مجلد وFolderItem.
تحديث
# == Schema Information
#
# Table name: folders
#
# id :integer not null, primary key
# name :string(255) not null
# parent_folder_id :integer
# user_id :integer not null
# folder_itens_count :integer default(0)
# created_at :datetime
# updated_at :datetime
#
class Folder < ActiveRecord::Base
...
belongs_to :parent_folder, :class_name => 'Folder'
has_many :child_folders, :class_name => 'Folder', :foreign_key => :parent_folder_id
has_many :folder_itens, :order => 'created_at DESC'
after_update {
update_parent_folder_itens_count
}
def update_parent_folder_itens_count
parent_folder = self.parent_folder
if self.folder_itens_count_changed? && parent_folder
quant_changed = self.folder_itens_count - self.folder_itens_count_was
parent_folder.increment(:folder_itens_count, quant_changed)
end
end
end
class FolderItem < ActiveRecord::Base
...
belongs_to :folder, :counter_cache => :folder_itens_count
end
أنا أستخدم counter_cache للاحتفاظ بعدد عناصر مجلد واحد.ولكن قد يكون المجلد هو الأصل لمجلد آخر، وأردت أن يحتوي المجلد الأصلي على مجموع ذاكرة التخزين المؤقت المضادة لكل العناصر التابعة له بالإضافة إلى ذاكرة التخزين المؤقت المضادة الخاصة به.
للقيام بذلك، حاولت وضع طريقة after_update للتخزين المؤقت للتغييرات التي تم إجراؤها في عمود counter_cache، ولكن بطريقة ما لا يتم استدعاء هذه الطريقة عند إنشاء FolderItem جديد.
المحلول
سأفعل شيئا من هذا القبيل.
أضف بعض حقول عداد ذاكرة التخزين المؤقت إلى جدول المجلدات
$ rails g migration add_cache_counters_to_folders child_folders_count:integer \
folder_items_count:integer \
total_items_count:integer \
sum_of_children_count:integer
وكود روبي
class Folder < ActiveRecord::Base
belongs_to :parent_folder, class_name: 'Folder', counter_cache: :child_folders_count
has_many :child_folders, class_name: 'Folder', foreign_key: :parent_folder_id
has_many :folder_items
before_save :cache_counters
# Direct descendants - files and items within this folder
def total_items
child_folders_count + folder_items_count
end
# All descendants - files and items within all the folders in this folder
def sum_of_children
folder_items_count + child_folders.map(&:sum_of_children).inject(:+)
end
private
def cache_counters
self.total_items_count = total_items
self.sum_of_children_count = sum_of_children
end
end
class FolderItem < ActiveRecord::Base
belongs_to :folder, counter_cache: true # folder_items_count
end
يرجى ملاحظة أن Folder#sum_of_children
- الطريقة متكررة، لذلك بالنسبة لمجموعات البيانات الكبيرة قد تؤدي إلى إبطاء تطبيقك.قد ترغب في القيام بمزيد من سحر SQL لها، ولكن نظرًا لأن روبي خالصة، فهذا أقرب ما يمكن إلى الحل الجيد الذي يمكنني الحصول عليه.لقد رأيت أنك فعلت ذلك في الاتجاه المعاكس، وسيكون ذلك بطيئًا تمامًا كما تحتاج إلى التحديث من الأسفل إلى الأعلى أيضًا.(هذا من أعلى إلى أسفل)
لا أعرف إذا كان هذا هو ما تبحث عنه، ولكنه حل قابل للقراءة للتخزين المؤقت لعدد العناصر داخل المجلد.