【问题标题】:Rails has_many through polymorphic counter cacheRails has_many 通过多态计数器缓存
【发布时间】:2013-03-21 11:04:36
【问题描述】:

我有两个模型我使用多态 has_many 通过关联链接在一起,我想添加一个 counter_cache 但似乎 Rails/ActiveRecord 不支持此功能。

class Classifiable < ActiveRecord::Base
  has_many :classifications, :as => :classifiable, :foreign_key => :classifiable_id
end

class Taxonomy < ActiveRecord::Base
  has_many :classifications, :as => :taxonomy, :foreign_key => :taxonomy_id
end

class Question < Classifiable
  has_many :categories, :through => :classifications, :as => :classifiable, :source => :taxonomy, :source_type => "Category"
end

class Category < Taxonomy
  has_many :questions, :through => :classifications, :source => :classifiable, :source_type => "Question"
end

class Classification < ActiveRecord::Base
  attr_accessible :classifiable, :classifiable_id, :classifiable_type,
                  :taxonomy, :taxonomy_id, :taxonomy_type

  belongs_to :classifiable, :polymorphic => true
  belongs_to :taxonomy,     :polymorphic => true
end

【问题讨论】:

    标签: ruby-on-rails activerecord polymorphism has-many-through counter-cache


    【解决方案1】:

    只需针对以下内容修改您的分类模型:

    class Classification < ActiveRecord::Base
      attr_accessible :classifiable, :classifiable_id, :classifiable_type,
                      :taxonomy, :taxonomy_id, :taxonomy_type
    
      belongs_to :classifiable, :polymorphic => true
      belongs_to :taxonomy,     :polymorphic => true
    
      before_create  :increment_counter
      before_destroy :decrement_counter
    
      private
    
      # increments the right classifiable counter for the right taxonomy
      def increment_counter
        self.taxonomy_type.constantize.increment_counter("#{self.classifiable_type.downcase.pluralize}_count", self.taxonomy_id)
      end
    
      # decrements the right classifiable counter for the right taxonomy
      def decrement_counter
        self.taxonomy_type.constantize.decrement_counter("#{self.classifiable_type.downcase.pluralize}_count", self.taxonomy_id)
      end
    end
    

    另外,请确保您的分类表中有以下列:

    t.integer :questions_count,           :null => false, :default => 0
    t.integer :other_classifiables_count, :null => false, :default => 0
    t.integer :other_classifiables_count, :null => false, :default => 0
    t.integer :other_classifiables_count, :null => false, :default => 0
    

    将“other_classifiables_count”更改为您需要的(“answers_count”、“users_count”等)

    【讨论】:

      【解决方案2】:

      在调用 delete 时,Rails 似乎没有经过 before/after_destroy 回调(当您删除 a 时会发生很多通过关联)。

      相反,您可以使用关联的回调 #before_add#before_remove

      class Question < Classifiable
        has_many :categories, through: :classifications, 
                              as: :classifiable, 
                              source: :taxonomy, 
                              source_type: Category,
                              before_add: :increment_counter
      
        def increment_counter(category)
          # increment counter, etc.
        end
      
      end
      

      【讨论】:

        【解决方案3】:

        要稍微修改乔纳森的答案,您可以让它在递增/递减之前查找列类型以查看它是否存在。我也把它弄干了一点:

        def increment_counter(direction=:increment)
          ar_class  = self.taxonomy_type.constantize
          ar_column = "#{self.taxonomy_type.underscore.pluralize}_count"
        
          if ar_class.columns.include? ar_column
            ar_class.send "#{direction}_counter", ar_column, self.taxonomy_id
          end
        end
        
        def decrement_counter
          increment_counter :decrement
        end
        

        哦,它适用于MultiWordClassNamesunderscore 执行 downcase 所以我的版本省略了它。

        【讨论】:

          猜你喜欢
          • 2020-03-07
          • 2012-04-11
          • 2013-07-08
          • 1970-01-01
          • 2014-12-16
          • 1970-01-01
          • 1970-01-01
          • 2012-03-17
          • 2017-10-26
          相关资源
          最近更新 更多