У вас есть несколько вариантов пропуска обновления кэша счетчика, и тот, который вы выберете, действительно зависит от того, как вы хотите структурировать свое приложение. Я расскажу о различных способах обхода кэша счетчиков и расскажу о некоторых соображениях, которые вы, возможно, захотите сделать при этом.
Как правило, существует три способа пропустить обновление кэша счетчика:
- Обезьяна исправит вашу модель, чтобы отключить обратный вызов счетчика кэша
- Используйте метод обновления, который не вызывает обратные вызовы
- Определите альтернативную модель, указывающую на ту же таблицу, которая не имеет такого же поведения обратного вызова, и используйте ее при массовой вставке в базу данных
Обратите внимание, что первые два вышеупомянутых параметра в более общем плане связаны с отключением обратных вызовов в ActiveRecord, и это имеет смысл, поскольку кэш счетчика реализован внутри посредством обратного вызова.
Когда Rails загружает модель, связанную с кэшем счетчика, он динамически определяет методы обратного вызова. Если вы хотите отключить их как обратный вызов, вы должны сначала выяснить, как называются обратные вызовы.
Существует два основных способа выяснить, какие методы определил Rails для реализации этих обратных вызовов. Вы можете прочитать исходный текст Rails, чтобы узнать имена, которые он собирается сгенерировать с помощью String Intorpolation, или вы можете использовать интроспекцию, чтобы выяснить, на какие методы отвечает ваш класс. Я приведу пример того, как вы можете использовать интроспекцию для определения обратных вызовов, определенных ActiveRecord, для автоматической реализации кэширования счетчика.
Предположим, у вас есть класс SpecialReply, который происходит от класса Reply, который происходит от ActiveRecord :: Base ( этот пример взят из набора тестов с Rails ). Он имеет столбец кэша счетчика, как определено ниже:
class SpecialReply < ::Reply
belongs_to :special_topic, :foreign_key => 'parent_id', :counter_cache => 'replies_count'
end
В консоли вы можете увидеть, на какие методы реагирует ваш класс, используя .methods
. Это создаст много шума, так как каждый экземпляр Object
уже реагирует на множество методов, поэтому вы можете сузить список следующим образом:
1.9.3-p194 :001 > sr = SpecialReply.new
1.9.3-p194 :002 > sr.methods - Object.methods
Во второй строке, которую вы говорите, покажите мне все методы, на которые отвечает мой экземпляр SpecialReply, за исключением тех, на которые отвечают все объекты. Это часто помогает с самоанализом, отфильтровывая методы, которые не относятся к типу класса, на который вы смотрите.
К сожалению, даже после этой фильтрации много шума из-за методов, которые ActiveRecord добавляет ко всем своим потомкам. В этом случае полезно grep
- поскольку ActiveRecord помогает создавать методы обратного вызова счетчика, содержащие строку counter_cache
( см. Метапрограммирование, используемое ActiveRecord для создания метода кэширования счетчика для belongs_to
ассоциации ) Вы можете узнать обратные вызовы, определенные для кэшей счетчиков, со следующими параметрами:
1.9.3-p194 :001 > sr = SpecialReply.new
1.9.3-p194 :002 > sr.methods.map(&:to_s).grep(/counter_cache/)
Обратите внимание, что, поскольку grep
работает со строкой, а methods
возвращает массив имен методов символов, мы сначала используем to_proc
(&:
) для преобразования всех символов в строки, а затем выполняем поиск те, которые содержат counter_cache
. Это оставляет меня со следующими методами, которые, кажется, были автоматически сгенерированы ActiveRecord как обратные вызовы для реализации кэширования счетчика:
belongs_to_counter_cache_after_create_for_special_topic
belongs_to_counter_cache_before_destroy_for_special_topic
belongs_to_counter_cache_after_create_for_topic
belongs_to_counter_cache_before_destroy_for_topic
belongs_to_counter_cache_after_create_for_topic_with_primary_key
belongs_to_counter_cache_before_destroy_for_topic_with_primary_key
Вы должны быть в состоянии выполнить аналогичный процесс в вашей программе, чтобы определить имена методов, добавленные ActiveRecord, чтобы вы могли их исключить, следуя существующим инструкциям по удалению обратных вызовов .
Ваш выбор из вышеперечисленных вариантов действительно зависит от структуры вашей программы и компромиссов, которые вы готовы рассмотреть для повышения эффективности загрузки данных. Следует отметить, что первые два параметра могут сделать ваш код менее читаемым, изменив поведение класса извне (исправление обезьян), и могут сделать вашу систему нестабильной, обходя бизнес-правила (обновления столбцов кэша) при обновлении данных. По этим причинам я бы подумал о том, можно ли создать другой класс для загрузки ваших данных оптимизированным способом, минимизируя при этом влияние на читаемость или согласованность данных.