I have a module that has multiple class variables. I’m looking for a class level getter implementation that will only instantiate the @@ variable when the class tries to access it like the following
module MyProducts
@@products = nil
def self.get_product(id)
# i'm looking for a way that the first call on @@products does a find via AR like the following
# @@products = Product.all
# this module is in the lib directory of a Rails 2.3.5 app
@@products.find do |prod|
prod.id.eql?(id)
end
end
end
I’m looking for this to be transparent so that i don’t have to modify the whole module. There are about 10 class level variables with similar functions, all the results of an ActiveRecord .find call
Just use the
||=operator. It would evaluate the right expression only if the right part isnilorfalseThe first time you call the method it will initialize the variable with the result of
some_value, and following calls will return the@@anyvalue with no need of recomputingsome_value.Update
Here it’s a little script which shows you how to do that. If you execute that you’ll see that the method
complex_functionis called once since the two print statements both returns 1. However from your comment I see that yourProductis an active record, so don’t use this approach for what your asking for, it will be very inefficient (read the last part of my answer)Update end
However your approach to save
Product.allis pretty inefficient:Replace your whole method with a
Product.find(id)call.If your
Productmodel isn’t stored in the db (maybe an ActiveResource) ignore my previous comment.You could also take a look to mattr_accessor and this SO question Difference between mattr_accessor and cattr_accessor in ActiveSupport?
Finally also take a look to this article which explains the above technique called memoization