# Action Association Caching

**URL:** <https://discuss.rubyonrails.org/t/action-association-caching/32731>\
**Category:** rubyonrails-talk\
**Created:** [August 3, 2008, 12:46pm UTC](https://discuss.rubyonrails.org/t/action-association-caching/32731 "2008-08-03T12:46:08Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![11175](https://avatars.discourse-cdn.com/v4/letter/1/8edcca/32.png) [@11175](https://discuss.rubyonrails.org/u/11175)\
**Post date:** [August 3, 2008, 12:46pm UTC](https://discuss.rubyonrails.org/t/action-association-caching/32731/1 "2008-08-03T12:46:08Z")

</div>

Hey again guys,

I did come up with a problem few weeks ago and I still don't have an elegant solution for it. I'd like to hear your opinions on how to deal with it, since it's rather basic and could be quite common.

Imagine a view showing peoples clothing. Stefan's hat: stefan.cloths.find\_by\_location "head" Stefan's shirt: stefan.cloths.find\_by\_location "shirt" Stefan's jeans: stefan.cloths.find\_by\_location "jeans" Stefan's left\_glove: stefan.cloths.find\_by\_location "left\_glove" Stefan's right\_glove: stefan.cloths.find\_by\_location "right\_glove" etc...

quite a few queries. bad performance. the thing is though, before reaching the view the association has been already initialized. so, the rows already exist in the action, and they are retrieved again one-by-one in the view.

to avoid retrieving them again, i build a hash in the action this way: for cloth in cloths; @cached\_clothes[cloth.location] = cloth; end and in the view: Stefan's hat: @cached\_clothes["head"]

It "works". But does not seem elegant. an other approach i tried: Stefan's hat: stefan.clothes.select{|c| c.location == "head"}.first Doesnt seem to be the correct "rails way" either.

Is there a "rails way" for doing this?

Thank you 😉Stefan

---

<div class="post-metadata">

**Author:** ![Frederick\_Cheung](https://sea2.discourse-cdn.com/rubyonrails/user_avatar/discuss.rubyonrails.org/frederick_cheung/32/3901_2.png) [@Frederick\_Cheung](https://discuss.rubyonrails.org/u/Frederick_Cheung)\
**Post date:** [August 3, 2008, 11:16pm UTC](https://discuss.rubyonrails.org/t/action-association-caching/32731/2 "2008-08-03T23:16:02Z")

</div>

> to avoid retrieving them again, i build a hash in the action this way: for cloth in cloths; @cached\_clothes[cloth.location] = cloth; end and in the view: Stefan's hat: @cached\_clothes["head"]

You can make this slightly neater by saying @cached\_clothes =  
stefan.clothes.index\_by {|c| c.location}

> It "works". But does not seem elegant. an other approach i tried: Stefan's hat: stefan.clothes.select{|c| c.location == "head"}.first Doesnt seem to be the correct "rails way" either.

Seems reasonable enough. If there were a lot of clothes and clothe  
locations the hash approach might be more efficient, but until then it  
could be over the top. If you wanted the syntax to be cleaner I suppose you could fiddle  
around with an association extension, eg

has\_many :clothes do &nbsp;&nbsp;&nbsp;def select\_by attribute, value &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;detect {|c| c.send(attribute) == value} &nbsp;&nbsp;&nbsp;end end

and then you can do stefan.clothes.select\_by :location, 'head' You could even go the whole hod and leverage method\_missing to handle  
things like clothes.select\_by\_location 'x'

If you're only ever doing this by location, you can make things a  
little shorter

has\_many :clothes do &nbsp;&nbsp;&nbsp;def located\_on place &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;detect {|c| c.location == place} &nbsp;&nbsp;&nbsp;end end

and then you can write stefan.clothes.located\_on 'head'

or apply association extensions to the first technique:

has\_many :clothes do &nbsp;&nbsp;&nbsp;def located\_on place &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@cache ||= index\_by {|c| c.location} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@cache[place] &nbsp;&nbsp;&nbsp;end end (this may or may not be a concern, but in this case you do need to  
worry about @cache getting stale, eg as is reloading the association  
won't clear it)

Fred

---

<div class="post-metadata">

**Author:** ![11175](https://avatars.discourse-cdn.com/v4/letter/1/8edcca/32.png) [@11175](https://discuss.rubyonrails.org/u/11175)\
**Post date:** [August 4, 2008, 12:47am UTC](https://discuss.rubyonrails.org/t/action-association-caching/32731/3 "2008-08-04T00:47:22Z")

</div>

Thanks again fred.

This association extension thing seems like the piece of the puzzle I was missing.
