3

関連を介してポリモーフィックな has_many を使用してリンクする 2 つのモデルがあり、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
4

3 に答える 3

10

次のように分類モデルを変更するだけです。

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」など) に変更します。

于 2013-03-31T01:25:18.973 に答える
3

Rails は、delete を呼び出すときに before/after_destroy コールバックを通過しないようです (関連付けを介して has many を削除するとどうなるか)。

代わりに、関連付けのコールバック#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
于 2014-07-09T21:23:48.757 に答える
2

ジョナサンの答えを少し変更するには、列の種類を調べて、インクリメント/デクリメントする前に存在するかどうかを確認することができます。私もそれを少し乾かしました:

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

ああ、それはで動作しMultiWordClassNamesます。underscore私のバージョンではdowncaseそれを省略しています。

于 2014-06-28T22:34:30.540 に答える