【问题标题】:counter_cache with has_many :through带有 has_many 的 counter_cache :通过
【发布时间】:2011-07-12 12:43:03
【问题描述】:

我刚刚创建了一个 counter_cache 字段,控制器看起来像这样。

 @users = User.where(:sex => 2).order('received_likes_count')

User.rb 中的关联是

 has_many :received_likes, :through => :attachments, :source => :likes, :dependent => :destroy

问题是 counter_cache 在 Like.rb 的 belongs_to 中声明,我不知道如何告诉它是为了 has_many :through 关联。

  belongs_to :user, :counter_cache => :received_likes

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-3


    【解决方案1】:

    你有以前的

        class Product
          has_and_belongs_to_many :categories
        end
    
        class Category
          has_and_belongs_to_many :products
        end
    

    和迁移

        class CreateCategoriesProducts < ActiveRecord::Migration
          def change
            create_table :categories_products, id: false do |t|
              t.references :category
              t.references :product
            end
    
            add_index :categories_products, [:category_id, :product_id]
          end
        end
    

    现在全部改为

        class Product
          has_many :categories_products, dependent: :destroy
          has_many :categories, through: :categories_products
        end
    
        class Category
          has_many :categories_products, dependent: :destroy
          has_many :products, through: :categories_products
        end
    

    还有新的

        class CategoriesProduct < ActiveRecord::Base
          # this model uses table "categories_products" as it is
          # column products_count is in the table "categories"
          belongs_to :category, counter_cache: :products_count
          belongs_to :product
        end
    

    【讨论】:

    • 换句话说,当您拥有has_many :through 关系时,您可以在:through 模型上定义任何和所有counter_cache。您可以通过扩展第二个关系来补充第一个 counter_cache: :products_count:belongs_to :product, counter_cache: :categories_count
    • 谢谢,在 Rails 4.2 上工作。要正确处理产品删除,需要在两个“has_many :categories_products”语句中添加“dependent::destroy”选项。
    • 这应该是答案。
    • 在 Rails 4.2 中按预期工作。
    • @TatianaTyu 在 Rails 4.1 上也一样
    【解决方案2】:

    这基本上做同样的事情:

    after_save :cache_post_count_on_tags
    
    def cache_post_count_on_tags
      tags.each {|t| tag.update_attribute(:posts_count, t.posts.size)}
    end
    

    你需要一个posts_count标签列,或者你有任何关联。

    【讨论】:

    • 其实我认为你的代码不会减少计数器,因为我认为 after_save 在 destroy() 之后没有被调用
    【解决方案3】:

    根据this post(从上个月开始)和this post(从2008 年开始),这似乎是不可能的。但是,后一篇文章确实有解决方法的代码(为方便起见,从该链接复制/粘贴,归功于第二个链接中的 DEfusion)

    class C < ActiveRecord::Base
        belongs_to :B
    
        after_create :increment_A_counter_cache
        after_destroy :decrement_A_counter_cache
    
        private
    
        def increment_A_counter_cache
            A.increment_counter( 'c_count', self.B.A.id )
        end
    
        def decrement_A_counter_cache
            A.decrement_counter( 'c_count', self.B.A.id )
        end
    end
    

    (这是一个方案,其中 C 属于 B,B 属于 A,A 有多个 C :through => B

    【讨论】:

    • Aivils 提供的解决方案看起来比添加钩子更正确/传统的 Rails 解决方案。
    猜你喜欢
    • 2023-03-07
    • 1970-01-01
    • 2015-11-23
    • 2011-04-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-19
    • 2011-06-30
    • 1970-01-01
    相关资源
    最近更新 更多