Просто используйте оператор ||=
.Правильное выражение будет оцениваться только в том случае, если правая часть равна nil
или false
def foo
@@any ||= some_value
end
При первом вызове метода он инициализирует переменную с результатом some_value
и послеВызовы будут возвращать значение @@any
без необходимости повторного ввода some_value
.
Обновление
Вот небольшой скрипт, который показывает вам, как это сделать.Если вы выполните его, то увидите, что метод complex_function
вызывается один раз, поскольку оба оператора print оба возвращают 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
довольно неэффективно:
- Сначала он извлечет все продуктов в базе данных, которые могут потреблять много памяти, когда у вас много продуктов
- Второй вашКод итерации будет намного медленнее, чем дБ, если у вас много продуктов
Замените весь ваш метод на вызов Product.find(id)
.
Если ваша модель Product
не существуетt хранится в БД (возможно, ActiveResource) игнорировать мой предыдущий комментарий.
Вы также можете взглянуть на mattr_accessor и этот вопрос SO Разница между mattr_accessor и cattr_accessor в ActiveSupport?
Наконец также посмотрите на эта статья , которая объясняет вышеупомянутую технику, называемую запоминанием