2008-10-07 41 views
2

Account模式有以下兩個協會:在條件子句中的ActiveRecord協會緩存日期值

has_many :expenses, 
      :order => 'expenses.dated_on DESC', 
      :dependent => :destroy 

has_many :recent_expenses, 
      :class_name => 'Expense', 
      :conditions => "expenses.dated_on <= '#{Date.today}'", 
      :order => 'dated_on DESC', 
      :limit => 5 

在我的觀點一個我最近渲染的費用,像這樣:

<% @account.recent_expenses.each do |expense| %> 
... 
<% end %> 

在我開發機器,登臺服務器(運行在生產模式下)以及生產控制檯上,@account.recent_expenses返回正確的列表。但是,在我們的實時生產服務器上,最新的費用不會返回。

如果我在視圖替換@account.recent_expenses@account.expenses,最近的費用顯示,所以我的猜測是,條件子句#{Date.today}部分以某種方式被緩存是第一次執行。如果我重新啓動生產Mongrel羣集,則所有最新費用都會正確返回。

任何人都可以想到爲什麼會發生這種情況,我如何更改:recent_expenses查詢以防止這種情況發生?

我正在使用Rails 2.1.0。

回答

6

Rails在加載時構建查詢,然後每次調用@ account.recent_expenses時都會重新使用該查詢,這正是您所遇到的情況。

如果您使用的是Rails 2.1,您可以使用named_scope來實現您正在尋找的內容。

費用模型,把下面的:

named_scope :recent, lambda { {:conditions => ["expenses.dated_on <= ?", Date.today], :order => 'dated_on DESC', :limit => 5 } } 

拉姆達被用來確保軌道的每一次重建查詢。

帳戶刪除:

has_many :recent_expenses ... 

,然後調用:

<% @account.expenses.recent.each do |expense| %> 
... 
<% end %> 
3

就像安德魯說,聯想宏在應用程序啓動時讀取,因此任何動態位(如Date.today )在那個時候被解析。如果你使用Rails 2.1或更高版本,他的解決方案就可以工作。對於早期版本中,你可以使用has_finder gem,或者只是建立在費用模型下面的方法:

def self.recent 
    find(:all, :conditions => ['dated_on <= ?', Date.today], :limit => 5, :order => 'dated_on DESC') 
end 

類方法像這樣暴露在協會,並適當範圍的 - 他們和named_scopes之間的區別是,你不能鏈接它們。

1

下面是它看起來像在Rails的3:

scope :recent, lambda { where("expenses.dated_on <= ?", Date.today).order('dated_on DESC').limit(5) } 

警告:當心未包裹在拉姆達鏈式範圍。您可能認爲鏈的一部分在運行時進行了評估,但可能會在應用服務器啓動時進行評估。確保你的lambda包裝將使用這些其他範圍的任何範圍。這裏解釋: http://www.slashdotdash.net/2010/09/25/rails-3-scopes-with-chaining/