Просто используйте оператор ||=
. Он будет оценивать правильное выражение только в том случае, если правая часть равна nil
или false
.
def foo
@@any ||= some_value
end
При первом вызове метода он инициализирует переменную с результатом some_value
, а последующие вызовы вернут значение @@any
без необходимости повторного вычисления some_value
.
Обновить
Вот небольшой скрипт, который показывает вам, как это сделать. Если вы выполните это, вы увидите, что метод complex_function
вызывается один раз, поскольку оба оператора печати возвращают 1. Однако из вашего комментария я вижу, что ваша Product
является активной записью, поэтому не используйте этот подход для того, что вы просите , это будет очень неэффективно (читайте последнюю часть моего ответа)
#!/usr/bin/env ruby
module Foo
def self.products
@@products ||=complex_function
end
@@a = 0
def self.complex_function
@@a += 1
end
end
p Foo.products
p Foo.products
Завершение обновления
Однако ваш подход к сохранению Product.all
довольно неэффективен:
- Сначала он извлечет все продукты из базы данных, что может занять много памяти, если у вас много продуктов.
- Во-вторых, ваш код итерации будет намного медленнее, чем db, когда у вас много продуктов.
Замените весь метод вызовом Product.find(id)
.
Если ваша модель Product
не хранится в базе данных (возможно, в ActiveResource), игнорируйте мой предыдущий комментарий.
Вы также можете взглянуть на mattr_accessor и на этот ТАК вопрос Разница между mattr_accessor и cattr_accessor в ActiveSupport?
Наконец, обратите внимание на эту статью что объясняет вышеупомянутую технику, называемую мемоизацией
person
Fabio
schedule
22.09.2011