Несколько экземпляров counter_cache в модели Rails
Я изучаю Rails, и у меня возникла небольшая проблема. Я пишу мертвое простое приложение со списками задач, поэтому модели выглядят примерно так:
class List < ActiveRecord::Base
has_many :tasks
has_many :undone_tasks, :class_name => 'Task',
:foreign_key => 'task_id',
:conditions => 'done = false'
# ... some validations
end
Таблица для модели List
имеет столбцы tasks_counter
и undone_tasks_counter
.
class Task < ActiveRecord::Base
belongs_to :list, :counter_cache => true
# .. some validations
end
С таким кодом есть экземпляры attr_readonly :tasks_counter
для List
, но я также хотел бы иметь счетчик для отмененных задач. Есть ли способ автоматического резервного копирования нескольких счетчиков с помощью Rails.
До сих пор мне удалось создать TasksObserver
, который увеличивает или уменьшает Task#undone_tasks_counter
, но, возможно, есть более простой способ.
Ответы
Ответ 1
Вы пробовали его с помощью столбца custom-counter-cache?
Док здесь:
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html
Предполагается, что вы можете передать имя столбца опции counter_cache, которую вы, возможно, сможете вызвать дважды, например
belongs_to :list, :counter_cache => true # will setup tasks_count
belongs_to :list, :counter_cache => :undone_tasks_count
Примечание: на самом деле не проверено.
Ответ 2
ez.
1) первый счетчик - автоматически выполнит
2) Вручную "правильно"
AnotherModelHere
belongs_to :user, counter_cache: :first_friends_count
after_create :provide_correct_create_counter_2
after_destroy :provide_correct_destroy_counter_2
def provide_correct_create_counter_2
User.increment_counter(:second_friends_count, another_user.id)
end
def provide_correct_destroy_counter_2
User.decrement_counter(:second_friends_count, another_user.id)
end
Ответ 3
Я не знаю ни одного "автоматизированного" метода для этого. Наблюдатели кажутся хорошими для этого, но я лично предпочитаю использовать обратные вызовы в модели (before_save
, after_save
).
Ответ 4
Скорее всего, вам понадобится counter_culture gem, так как он может обрабатывать счетчики с пользовательскими условиями и будет обновлять значение счетчика не только для создания и уничтожить, но и обновления:
class CreateContainers < ActiveRecord::Migration[5.0]
create_table :containers, comment: 'Our awesome containers' do |t|
t.integer :items_count, default: 0, null: false, comment: 'Caching counter for total items'
t.integer :loaded_items_count, default: 0, null: false, comment: 'Caching counter for loaded items'
end
end
class Container < ApplicationRecord
has_many :items, inverse_of: :container
has_many :loaded_items, -> { where.not(loaded_at: nil) },
class_name: 'Item',
counter_cache: :loaded_items_count
# Notice that you can specify custom counter cache column name
# in has_many definition and AR will use it!
end
class Item < ApplicationRecord
belongs_to :container, inverse_of: :items, counter_cache: true
counter_culture :container, column_name: proc { |model| model.loaded_at.present? ? 'loaded_items_count' : nil }
# But this column value will be handled by counter_culture gem
end