我正在学习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
,但也许有一种更简单的方法。
答案 0 :(得分:22)
您是否尝试使用自定义计数器缓存列? 这里的文件: 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
注意:未进行实际测试。
答案 1 :(得分:0)
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
答案 2 :(得分:-1)
很可能你需要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
答案 3 :(得分:-2)
我不知道任何“自动”方法。观察者似乎对此很好,但我个人更喜欢在模型中使用回调(before_save
,after_save
)。