2009-12-02 20 views
0

在Rails,自動計數協會,你這樣做:傳遞軌協會和神奇數

class Script 
    has_many :chapters 
end 
class Chapter 
    belongs_to :script 
end 

和你添加一個chapters_count列到腳本模型。

現在,如果要在段落模型中沒有script_id鍵的情況下計算腳本中的段落數,該怎麼辦?

class Script 
    has_many :chapters 
    has_many :paragraphs # not complete 
end 
class Chapter 
    has_many :paragraphs 
    belongs_to :script 
end 
class Paragraph 
    belongs_to :chapter 
end 

你怎麼自動關聯腳本段落和使用Rails的自動計數數得過來?

回答

1

你在正確的軌道上。但首先你必須解決一個小錯誤。除非您指示它,否則Rails不會更新計數器緩存。

class Chapter 
    belongs_to :script, :counter_cache => true 
end 

將在創建之前和銷燬所有關聯的章節之後自動更新@ script.chapter_count。

不幸的是事情並非如此簡單,當處理:通過關係。您需要通過段落模型中的回調來更新關聯的腳本的段落計數器。

N.B .:以下假設您還想在章節中保留段落計數器。

首先將相同的理論應用於章模型,並將段落計數列應用於腳本表。

class PrepareForCounterCache < ActiveRecord::Migration 
    def self.up 
    add_column :scripts, :paragraphs_count, :integer, :default => 0 
    add_column :chapters, :paragraphs_count, :integer, :default => 0 

    Chapter.reset_column_information 
    Script.reset_column_information 

    Chapter.find(:all).each do |c| 
     paragraphs_count = c.paragraphs.length 
     Chapter.update_counters c.id, :paragraphs_count => paragraphs_count 
     Script.update_counters c.script_id, :paragraphs_count => paragraphs_count 
    end 
    end 
    def self.down 
    remove_column :scripts, :paragraphs_count 
    remove_column :chapters, :paragraphs_count 
    end 
end 

我們建立的關係:

class Script 
    has_many: chapters 
    has_many: paragraphs, :through => :chapters 
end 

class Chapter 
    has_many: paragraphs 
    belongs_to :script, :counter_cache => true 
end 

class Paragraph 
    belongs_to :chapter, :counter_cache => true 
end 

剩下要做的事情就是告訴段落更新腳本中的段落計數器作爲回調。

class Paragraph < ActiveRecord::Base 
    belongs_to :chapter, :counter_cache => true 
    before_save :increment_script_paragraph_count 
    after_destroy, :decrement_script_paragraph_count 

    protected 
    def increment_script_paragraph_count 
    Script.update_counters chapter.script_id, :paragaraphs_count => 1 
    end 
    def decrement_script_paragraph_count 
    Script.update_counters chapter.script_id, :paragaraphs_count => -1 
    end 
end 
0

快速和簡單的方法,而無需使用的緩存是做:

class Script 
    has_many :chapters 
    has_many :paragraphs, :through => :chapters 
end 

script = Script.find(1) 
puts script.paragraphs.size #get the count 
+0

真奇怪,我認爲傳遞聯想沒有工作,因爲script.paragraphs.size是伊蓋爾爲0。但script.paragraphs.length是正確的。 但我真的很喜歡tiouse段落計數,自動Rails計數。 – MickaelFM 2009-12-03 18:04:34

+0

這是一個導軌功能(由has_many添加的方法)。 counter_cache在has_many:through上不起作用,因爲緩存是在belongs_to端實現的。你必須寫自己的,這裏是一個例子:http://www.ruby-forum.com/topic/138094#614246 – MattMcKnight 2009-12-03 19:07:35