2012-04-02 28 views
3

任何人都可以幫助我計算一個Rails應用程序中的偉大孫子記錄的數量?如何在Rails應用程序中計算偉大的孫子對象?

例如,我想要做的東西像下面這樣:

class Country 
    has_many :states 
    has_many :cities, :through => :states 
    has_many :events, :through => :cities 
end 

class State 
    belongs_to :country 
    has_many :cities 
    has_many :events, :through => :cities 
end 

class City 
    has_one :country, :through => state 
    belongs_to :state 
    has_many :events 
end 

class Event 
    belongs_to :city, :counter_cache => true 
    has_one :state, :through => city, :counter_cache => true 
    has_one :country, :through => :state, :counter_cache => true 
end 

所以我想訪問每個城市的事件的數量,每個國家和每個國家。

我有城市和州工作,但似乎無法得到在grandparent國家模型上運行的counter_cache。

我錯過了什麼嗎?這可能嗎?有沒有更好的方法來做到這一點?

我真的很感謝來自社區的一些想法。謝謝!

回答

1

你看過計數器緩存railscasts插曲嗎?這可能會有所幫助。

http://railscasts.com/episodes/23-counter-cache-column

如果你只是想數下幾個級別,你可以鏈接幾個語句來得到你的答案。但是,這不會非常高效,因爲需要多個數據庫調用才能完成此操作,因此如果要經常執行此計數,緩存計數會更好。

這裏是讓所有的事件的數量在一個國家的例子(未經測試),是這樣的:

country = Country.find(params[:id]) 
number_of_events_in_country = 0 
country.states.each{|s| s.cities.each{|c| number_of_events_in_country += c.events.count}} 
+0

感謝您的建議normalocity。我寧願緩存櫃檯。你有沒有試圖通過長期協會來計算?我無法弄清楚爲什麼我的實現無法正常工作。似乎它應該....?想知道我是否錯過了一些明顯的東西。 – 2012-04-02 14:01:30

+0

是的,我已經通過'has_many:through'關聯來完成計數,但是隻對沒有幾個級別的孫子(不是孫輩)有效。然而,我想這應該看起來像(在'app/models/country.rb'中)'has_many:events,:through =>:states',在'app/models/state.rb'中有一個等價的'has_many:事件,:through =>:cities',在'app/models/city.rb'中有一個等效的'has_many:events'。我認爲這種鏈接可能會起作用。 – jefflunt 2012-04-02 14:08:29

+0

緩存計數器會簡單得多。所以,當創建一個'event'時,它會做'event.city.update_attribute(:event_count_cache,event.city.event_count_cash + 1)',然後在'event.city.state'上加上一個類似的計數緩存增量等等,增加每個級別的計數器。當然,您需要確保如果事件被破壞,緩存計數器在相反的情況下被更新,並且如果事件改變了城市,則緩存計數器全部遞減,而不是與新遞增一起遞增城市/州等 – jefflunt 2012-04-02 14:11:18

1

如果它是你可以使用has_many通過(如你上面列出)祖父母關係,但你有一個很好的祖父母關係,這不適用於此。

你可以做的一件事情(如果你有多個級別的父子關係)在你的Country類中放一個方法來解析它。

class Country 
    has_many :states 
    has_many :cities, :through => :states 
    attr_accessor :events 

    def initialize 
    @events = Array.new 
    end 

    def get_events 
    self.states.each{|s| s.each{|c| c.each{|e| @events << e }}} 
    end 

end 

然後,只需調用get_events方法,事件將填充所有與第一條記錄關聯的事件。

usa = Country.first 
usa.get_events 
usa.events 
相關問題