2011-03-10 2 views
22

Я только что создал поле counter_cache, и контроллер выглядит так.counter_cache с has_many: через

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

Ассоциация в User.rb является

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

Проблема заключается в том, что counter_cache объявлен в belong_to из Like.rb, и я не знаю, как сказать ему, что это для has_many: через ассоциацию.

belongs_to :user, :counter_cache => :received_likes 

ответ

13

Согласно this post (с прошлого месяца) и this post (с 2008), это не представляется возможным. Однако последний пост имеет код для обхода (копировать/paste'd от этой ссылки для вашего удобства Заслуга 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 belongs_to B , B belongs_to A, A has_many C: через => B

+1

Решение, предлагаемое Aivils выглядит более правильный/монастырь Rails, чем добавление крючков. – jakeonrails

3

Это в основном делает то же самое:.

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 колонку на тегах, или что-то ассоциации у вас есть

+4

На самом деле, я думаю, что ваш код не уменьшит счетчик, потому что after_save, я думаю, не вызван после destroy() – pixelearth

21

У вас есть предыдущая

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 
+0

Это сработало прекрасно для меня. –

+0

Другими словами, если у вас есть отношение 'has_many: through', вы определяете все и все' counter_cache' на модели ': through'. Вы можете дополнить первый 'counter_cache:: product_count', расширив второе отношение:' принадлежит_то: product, counter_cache:: categories_count' –

+2

Спасибо, работает над Rails 4.2. Чтобы правильно обработать удаление продукта, необходимо добавить опцию «dependable:: destroy» для операторов «has_many: categories_products». –

Смежные вопросы