2016-04-30 44 views
0

我正在尋找一種方法來顯示有多少imagescategory,但通過has_many關聯獲得。我一直在閱讀上counter_cache一點點,但至今尚無歡樂上實現有效的方法來計算關聯的對象 - Rails 4

class Category < ActiveRecord::Base 
    has_many :image_categories 
    has_many :images, through: :image_categories 
end 

class ImageCategory < ActiveRecord::Base 
    # Holds image_id and category_id to allow multiple categories to be saved per image, as opposed to storing an array of objects in one DB column 
    belongs_to :image 
    belongs_to :category 
end 

class Image < ActiveRecord::Base 
    # Categories 
    has_many :image_categories, dependent: :destroy 
    has_many :categories, through: :image_categories 
end 

控制器

@categories = Category.all 

查看

<% @categories.each do |c| %> 
    <li> 
    <%= link_to '#', data: { :filter => '.' + c.name.delete(' ') } do %> 
     <%= c.name %> (<%= #count here %>) 
    <% end %> 
    </li> 
<% end %> 

如果有人可以幫助那些將不勝感激

謝謝

回答

2

既然你正在尋找一種有效的方式,我會建議使用counter_cache

下面是你的模型應該是這樣的:

class Category < ActiveRecord::Base 
    has_many :image_categories 
    has_many :images, through: :image_categories 
end 

class ImageCategory < ActiveRecord::Base 
    # Holds image_id and category_id to allow multiple categories to be saved per image, as opposed to storing an array of objects in one DB column 
    belongs_to :image, counter_cache: :category_count 
    belongs_to :category, counter_cache: :image_count 
end 

class Image < ActiveRecord::Base 
    # Categories 
    has_many :image_categories, dependent: :destroy 
    has_many :categories, through: :image_categories 
end 

你需要image_count字段添加到您的categories表和category_countimages表中。

一旦完成添加計數器和字段,您需要重置計數器,以便使用正確的計數值爲您的數據庫中已存在的記錄更新字段。

考慮與 counter_cache
Category.find_each { |category| Category.reset_counters(category.id, :images) } 

Image.find_each { |image| Image.reset_counters(image.id, :categories) } 
+0

謝謝,關於如何實現的任何想法?如上所述,尚未成功實施 – Richlewis

+0

@Richlewis請參閱更新後的答案 – Alfie

+1

請注意,您可能需要使用'reset_counters'將count列初始化爲其正確值'http://apidock.com/rails/ ActiveRecord/CounterCache/reset_counters' –

2

幾個重要的事情:繞過回調(例如update_columnupdate_allincrementdecrementdelete_all等)

  • 某些Rails的方法可以更新數據庫,並能導致計數器緩存的值不一致。這同樣適用於Rails之外的任何數據庫更改。
  • 創建/刪除子模型始終需要更新父級。爲了確保計數器緩存的一致性Rails在此更新期間使用額外的數據庫事務。這通常不是問題,但是如果您的子模型經常被創建/刪除,或者父模型經常更新,可能會導致數據庫死鎖。 (http://building.wanelo.com/2014/06/20/counter-cache-a-story-of-counting.html

由於您在連接表中使用計數器緩存,所以這些問題會加劇。

如果你想要做一個有效的動態計數,這始終是最新的,那麼你可以使用自定義select與分組聯接:

@categories = Category.select("categories.*, COUNT(DISTINCT images.id) AS images_count").joins(:images).group("categories.id") 

<% @categories.find_each do |c| %> 
    <li> 
    <%= link_to '#', data: { :filter => '.' + c.name.delete(' ') } do %> 
     <%= c.name %> (<%= c.images_count # <- dynamic count column %>) 
    <% end %> 
    </li> 
<% end %> 

的這個分組的成本加入應該很小提供你的外鍵被編入索引,如果你需要images_count始終與真實值一致,或者圖像經常被創建或銷燬,我會強烈考慮採用這種方法。從長遠來看,這種方法也可能更容易維護。

+0

謝謝,這看起來更容易維護,並在更新記錄時節省了我的痛苦。 – Richlewis

相關問題