# Lazy-load model class variable hash

**URL:** <https://www.ruby-forum.com/t/lazy-load-model-class-variable-hash/131249>\
**Category:** Rails\
**Created:** [March 7, 2008, 10:47am UTC](https://www.ruby-forum.com/t/lazy-load-model-class-variable-hash/131249 "2008-03-07T10:47:23Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![giantcranes](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/ecd19e/32.png) [@giantcranes](https://www.ruby-forum.com/u/giantcranes)\
**Post date:** [March 7, 2008, 10:47am UTC](https://www.ruby-forum.com/t/lazy-load-model-class-variable-hash/131249/1 "2008-03-07T10:47:23Z")

</div>

Hi,

I have a number of models which contain almost static data. I don’t want  
to hit to db when accessing a row, nor do I want to hit memcached.

I am hoping to use a lazy-loaded model class variable hash. This will  
ensure that the db is hit only once for the life of a mongrel process.

Are there any drawbacks to this solution? Can the code be simplified?

class Status \< Activerecord:Base  
@@hash\_by\_name = nil  
def self.hash\_by\_name  
unless @@hash\_by\_name  
@@hash\_by\_name = Hash.new  
Status.find(:all).each { |status| @@hash\_by\_name[status.name] =  
status }  
end  
@@hash\_by\_name  
end  
end

#Allowing me to do something like this:

puts Status.hash\_by\_name[‘pending’].id

Thanks,  
GiantCranes

---

<div class="post-metadata">

**Author:** ![giantcranes](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/ecd19e/32.png) [@giantcranes](https://www.ruby-forum.com/u/giantcranes)\
**Post date:** [March 7, 2008, 10:56am UTC](https://www.ruby-forum.com/t/lazy-load-model-class-variable-hash/131249/2 "2008-03-07T10:56:36Z")

</div>

On 7 Mar 2008, at 09:47, Giant C. wrote:

> Are there any drawbacks to this solution? Can the code be simplified?

well it’s very minor, but you can write  
@@hash\_by\_name = Status.find(:all).index\_by(&:name)

I’ve used a similar pattern quite a lot and as far as I can tell it  
works fine. If you are going to be using it in a lot of methods, then  
you can wrap it up a little, i’ve got something like

module Caches  
module ClassMethod  
def caches(name, &block)  
define\_method(name) do  
ivar\_name = “cache\_#{name}\_value”  
unless value = instance\_variable\_get ivar\_name  
value = instance\_eval(&block)  
instance\_variable\_set ivar\_name, value  
end  
value  
end  
end  
end  
def self.included(base)  
base.extend ClassMethods  
end  
end  
(written off the top of my head in mail, expect typos).

You can then do something like

class Status …  
class \<\< self  
include Caches  
caches(‘all’) {Status.find(:all).index\_by(&:name)}  
caches(‘something\_else’) { …code to compute something else…}  
end  
end

Fred

---

<div class="post-metadata">

**Author:** ![giantcranes](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/ecd19e/32.png) [@giantcranes](https://www.ruby-forum.com/u/giantcranes)\
**Post date:** [March 7, 2008, 11:20am UTC](https://www.ruby-forum.com/t/lazy-load-model-class-variable-hash/131249/3 "2008-03-07T11:20:10Z")

</div>

Thanks Frederick, with your help I’ve reduced the code to:

class Status \< ActiveRecord::Base  
def self.hash\_by\_name  
@@hash\_by\_name ||= self.find(:all).index\_by(&:name)  
end  
end

I’ll use the helper method if I use this a lot in the future.

Thanks!
