Работа приложения Rails или как кэшировать результат метода - PullRequest
1 голос
/ 08 июня 2010

У меня есть две модели:

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 вместо событий в методах.НО я не хочу загружать события при загрузке объекта - я хочу "кэшировать" события, только если был вызван какой-либо из этих трех методов, а другие методы должны использовать кэшированную версию событий.

Ответы [ 2 ]

1 голос
/ 08 июня 2010

Я полагаю, вы можете использовать следующее для загрузки 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
0 голосов
/ 08 июня 2010

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.

...