【问题标题】:counter_cache with conditions带条件的 counter_cache
【发布时间】:2011-11-19 12:45:10
【问题描述】:

我知道我可以使用回调,但这应该是可行的。我做了长时间的搜索,没有结果。这是我认为可行的。

def User < ActiveRecord::Base
  has_many :documents
  has_many :draft_docs     , :class_name => 'Document', :conditions => { :status => 'draft' }
  has_many :published_docs , :class_name => 'Document', :conditions => { :status => 'published' }
  has_many :private_docs   , :class_name => 'Document', :conditions => { :status => 'private' }
end

def Document < ActiveRecord::Base
  belongs_to :user      , :counter_cache => true
  belongs_to :user      , :inverse_of => :draft_docs    , :counter_cache => true
  belongs_to :user      , :inverse_of => :published_docs, :counter_cache => true
  belongs_to :user      , :inverse_of => :private_docs  , :counter_cache => true
end

没有按计划工作,因为您可以看到它正在更新documents_count 而不是published_docs_count。

ruby-1.9.2-p180 :021 > User.reset_counters 2, :published_docs  User Load (0.4ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` = 2 LIMIT 1
   (0.7ms)  SELECT COUNT(*) FROM `documents` WHERE `documents`.`user_id` = 2 AND `documents`.`status` = 'published'
   (2.2ms)  UPDATE `users` SET `documents_count` = 233 WHERE `users`.`id` = 2
 => true

【问题讨论】:

    标签: ruby-on-rails activerecord conditional counter-cache


    【解决方案1】:

    使用counter_culture gem。

    • 向users 表添加三列。

      add_column :users, :draft_documents_count, :integer, null: false, default: 0
      add_column :users, :published_documents_count, :integer, null: false, default: 0
      add_column :users, :private_documents_count, :integer, null: false, default: 0
      
    • 装饰Document 模型

      class Document
        counter_culture :user, :column_name => Proc.new do |doc|
          if %w(draft published private).include?(doc.status) 
            "{doc.status}_documents_count"
          end
        end    
      end
      
    • 在控制台中运行命令以播种当前行的计数

      Document.counter_culture_fix_counts
      

    旧答案

    您可以将计数器列名称(true 除外)提供给 counter_cache 选项。

    class Document < ActiveRecord::Base
      belongs_to :user, :counter_cache => true
      belongs_to :user, :inverse_of => :draft_docs, 
                                       :counter_cache => :draft_docs_count
      belongs_to :user, :inverse_of => :published_docs, 
                                       :counter_cache => :published_docs_count
      belongs_to :user, :inverse_of => :private_docs, 
                                       :counter_cache => :private_docs_count
    end
    

    【讨论】:

    • 它不起作用,它仍然只尝试更新documents_count。
    • 这不起作用。至少在 Rails 4 中不行。我怀疑它在 Rails 3.x 中也不起作用。
    【解决方案2】:

    这是因为您对所有关联使用相同的名称。

    belongs_to :user, :counter_cache => true
    belongs_to :user_doc, :class_name => "User", 
               :inverse_of => :draft_docs, :counter_cache => :draft_docs_count
    

    此功能是通过添加回调来增加计数来实现的,在您的情况下,目标是 document.user,因为您对所有内容都使用了相同的名称。

    【讨论】:

    • 我看不出这个答案与 Harish Shetty 提供的答案有何不同。在 SO 上,建议在回复时为问题带来新的东西。 :)
    • 这在 Rails 4 中不起作用。我怀疑它在 Rails 3.x 中也不起作用。你测试过这个吗?
    猜你喜欢
    • 1970-01-01
    • 2011-07-12
    • 2023-03-07
    • 1970-01-01
    • 2021-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    相关资源
    最近更新 更多