модуль ActiveRecord::CounterCache::ClassMethods
Публичные методы экземпляров
# File activerecord/lib/active_record/counter_cache.rb, line 121 def decrement_counter(counter_name, id) update_counters(id, counter_name => -1) end
Уменьшает числовое поле на единицу с помощью прямого обновления SQL.
Этот метод работает так же, как #increment_counter, но уменьшает значение столбца на 1 вместо увеличения.
Параметры
-
counter_name- Имя поля, которое должно быть уменьшено. -
id- Идентификатор объекта, который должен быть уменьшен, или массив идентификаторов.
Примеры
# Decrement the post_count column for the record with an id of 5 DiscussionBoard.decrement_counter(:post_count, 5)
# File activerecord/lib/active_record/counter_cache.rb, line 103 def increment_counter(counter_name, id) update_counters(id, counter_name => 1) end
Увеличивает числовое поле на единицу с помощью прямого обновления SQL.
Этот метод используется в основном для поддержания столбцов counter_cache, которые используются для хранения агрегированных значений. Например, DiscussionBoard может кэшировать posts_count и comments_count, чтобы избежать выполнения запроса SQL для подсчета количества постов и комментариев каждый раз, когда он отображается.
Параметры
-
counter_name- Имя поля, которое должно быть увеличено. -
id- Идентификатор объекта, который должен быть увеличен, или массив идентификаторов.
Примеры
# Increment the post_count column for the record with an id of 5 DiscussionBoard.increment_counter(:post_count, 5)
# File activerecord/lib/active_record/counter_cache.rb, line 20
def reset_counters(id, *counters)
object = find(id)
counters.each do |counter_association|
has_many_association = _reflect_on_association(counter_association)
unless has_many_association
has_many = reflect_on_all_associations(:has_many)
has_many_association = has_many.find { |association| association.counter_cache_column && association.counter_cache_column.to_sym == counter_association.to_sym }
counter_association = has_many_association.plural_name if has_many_association
end
raise ArgumentError, "'#{self.name}' has no association called '#{counter_association}'" unless has_many_association
if has_many_association.is_a? ActiveRecord::Reflection::ThroughReflection
has_many_association = has_many_association.through_reflection
end
foreign_key = has_many_association.foreign_key.to_s
child_class = has_many_association.klass
reflection = child_class._reflections.values.find { |e| e.belongs_to? && e.foreign_key.to_s == foreign_key && e.options[:counter_cache].present? }
counter_name = reflection.counter_cache_column
stmt = unscoped.where(arel_table[primary_key].eq(object.id)).arel.compile_update({
arel_table[counter_name] => object.send(counter_association).count(:all)
}, primary_key)
connection.update stmt
end
return true
end Сбрасывает один или несколько счетчиков кэша до правильного значения с помощью запроса SQL count. Это полезно при добавлении новых кэшированных счетчиков или если счетчик был поврежден или изменен напрямую с помощью SQL.
Параметры
-
id- Идентификатор объекта, для которого вы хотите сбросить счетчик. -
counters- Один или несколько счетчиков ассоциаций для сброса. Может быть указано имя ассоциации или имя счетчика.
Примеры
# For Post with id #1 records reset the comments_count Post.reset_counters(1, :comments)
# File activerecord/lib/active_record/counter_cache.rb, line 77
def update_counters(id, counters)
updates = counters.map do |counter_name, value|
operator = value < 0 ? '-' : '+'
quoted_column = connection.quote_column_name(counter_name)
"#{quoted_column} = COALESCE(#{quoted_column}, 0) #{operator} #{value.abs}"
end
unscoped.where(primary_key => id).update_all updates.join(', ')
end Универсальная реализация «обновления счетчиков», предназначенная в первую очередь для использования методами #increment_counter и #decrement_counter, но которая также может быть полезна сама по себе. Она просто выполняет прямое обновление SQL для записи с заданным идентификатором, изменяя заданный хэш счетчиков на величину, указанную соответствующим значением:
Параметры
-
id- Идентификатор объекта, на котором вы хотите обновить счетчик, или массив идентификаторов. -
counters- Хэш, содержащий имена полей для обновления в качестве ключей и величину изменения поля в качестве значений.
Примеры
# For the Post with id of 5, decrement the comment_count by 1, and # increment the action_count by 1 Post.update_counters 5, comment_count: -1, action_count: 1 # Executes the following SQL: # UPDATE posts # SET comment_count = COALESCE(comment_count, 0) - 1, # action_count = COALESCE(action_count, 0) + 1 # WHERE id = 5 # For the Posts with id of 10 and 15, increment the comment_count by 1 Post.update_counters [10, 15], comment_count: 1 # Executes the following SQL: # UPDATE posts # SET comment_count = COALESCE(comment_count, 0) + 1 # WHERE id IN (10, 15)
© 2004–2018 David Heinemeier Hansson
Licensed under the MIT License.