我有两种模式:
Program < ActiveRecord::Base
has_many :events
def federal_financing
events.sum(&:federal_financing)
end
def regional_financing
events.sum(&:regional_financing)
end
def local_financing
events.sum(&:local_financing)
end
end
Event < ActiveRecord::Base
belongs_to :program
# events table have this decimal fields: federal_financing, local_financing, regional_financing
end
总是如果我打电话给这三种方法中的一种,我会打电话给另一种方法。因此,每次调用这些方法时,我都希望避免加载事件。目前的解决方案是定义
def after_initialize
@all_events = events
end
并使用@all_events而不是方法中的事件。但是我不想在加载对象时加载事件 - 只有在调用这三个方法中的任何一个并且其他方法应该使用缓存版本的事件时,我才想要“缓存”事件。
答案 0 :(得分:1)
我相信您可以使用以下内容每events
加载一次program
:
Program < ActiveRecord::Base
has_many :events
def federal_financing
all_events.sum(&:federal_financing)
end
def regional_financing
all_events.sum(&:regional_financing)
end
def local_financing
all_events.sum(&:local_financing)
end
def all_events
# if @events is not initialized yet or is nil or is false,
# self.events will be loaded. otherwise @events will remain unchanged.
@events ||= self.events
end
end
答案 1 :(得分:0)
Rails将缓存自动加载事件的查询,因此您无需显式缓存事件。但是,要实现此功能,您需要在计算总和之前将事件转换为数组; events.sum
表示您希望构造一个SQL查询来计算总和,并且不起作用。
按如下方式更改Program
模型:
Program < ActiveRecord::Base
has_many :events
def federal_financing
events.to_a.sum(&:federal_financing)
end
def regional_financing
events.to_a.sum(&:regional_financing)
end
def local_financing
events.to_a.sum(&:local_financing)
end
end
现在,通过在控制台中启用ActiveRecord日志记录,很容易看到查询确实被缓存:
$ script/console
>> ActiveRecord::Base.logger = Logger.new(STDOUT)
>> p = Program.first
Program Load (1.0ms) SELECT * FROM "programs" LIMIT 1
=> #<Program id: 1, created_at: "2010-06-08 15:01:08", updated_at: "2010-06-08 15:01:08">
>> p.federal_financing
Event Load (1.0ms) SELECT * FROM "events" WHERE ("events".program_id = 1)
=> 147
>> p.regional_financing
=> 23
>> p.local_financing
=> 11
如您所见,在第一次调用federal_financing
期间,事件仅加载一次。