我的Account
模型有以下两种关联:
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。
答案 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 } }
lambda用于确保rails每次都重建查询。
从帐户删除:
has_many :recent_expenses ...
然后致电:
<% @account.expenses.recent.each do |expense| %>
...
<% end %>
答案 1 :(得分:3)
就像Andrew说的那样,在应用程序启动时会读取关联宏,因此在那时会解析任何动态位(如Date.today)。如果您使用Rails 2.1或更高版本,他的解决方案就可以工作;对于早期版本,您可以使用has_finder gem,或者只在Expense模型上创建以下方法:
def self.recent
find(:all, :conditions => ['dated_on <= ?', Date.today], :limit => 5, :order => 'dated_on DESC')
end
像这样的类方法暴露给关联,并且是适当的范围 - 它们和named_scopes之间的区别在于你不能链接它们。
答案 2 :(得分:1)
以下是Rails 3中的内容:
scope :recent, lambda { where("expenses.dated_on <= ?", Date.today).order('dated_on DESC').limit(5) }
警告: 注意未包含在lambda中的链式范围。您可能认为链的一部分是在运行时评估的,但可以在应用服务器启动时进行评估。确保lambda包装将使用这些其他范围的任何范围。这里的解释: http://www.slashdotdash.net/2010/09/25/rails-3-scopes-with-chaining/