# Caching of database values

**URL:** <https://www.ruby-forum.com/t/caching-of-database-values/92579>\
**Category:** Rails\
**Created:** [April 21, 2007, 12:26am UTC](https://www.ruby-forum.com/t/caching-of-database-values/92579 "2007-04-21T00:26:14Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![plambert](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/9d8465/32.png) [@plambert](https://www.ruby-forum.com/u/plambert)\
**Post date:** [April 21, 2007, 12:26am UTC](https://www.ruby-forum.com/t/caching-of-database-values/92579/1 "2007-04-21T00:26:14Z")

</div>

If do something like this:  
dbObj = MyTable.find\_by\_id(5)  
a = dbObj.name  
b = dbObj.name

How many times will an SQL call be made to get the value of  
MyTable.name for id 5? In other words, are the values for dbObj  
cached in the object? Is there a way of controlling that? (I can  
imagine that sometimes you might not want to cache them if you wanted  
to be sure of having the latest value.)

Thanks,  
–Paul

---

<div class="post-metadata">

**Author:** ![plambert](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/9d8465/32.png) [@plambert](https://www.ruby-forum.com/u/plambert)\
**Post date:** [April 21, 2007, 12:49am UTC](https://www.ruby-forum.com/t/caching-of-database-values/92579/2 "2007-04-21T00:49:15Z")

</div>

Only one db query is performed. The result is stored in your dbObj  
variable. If you want to “refresh” your in memory copy call reload:

dbObj.reload

A good way to monitor what rails is doing on the back end is to run a  
tail -f on the log. You’ll see every sql query and result.

Aaron

---

<div class="post-metadata">

**Author:** ![plambert](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/9d8465/32.png) [@plambert](https://www.ruby-forum.com/u/plambert)\
**Post date:** [April 21, 2007, 4:02pm UTC](https://www.ruby-forum.com/t/caching-of-database-values/92579/3 "2007-04-21T16:02:13Z")

</div>

Hello Paul,

You are indeed correct; all results from the find are cached in  
memory as attributes of the MyTable object.

I believe ActiveRecord gives you an option to achieve what you want  
through the use of transactions and locking. You can do the following:

MyTable.transaction do  
dbObj = MyTable.find\_by\_id(5, :lock =\> true)  
a = dbObj.name  
b = dbObj.name  
end

The above will ensure that you get an exclusive lock to the table/row  
you want to work with, inside the transaction block. No other process  
will get access to that row until your transaction is finished.

If you don’t want to lock the row (or table depending on the DB you  
use) then you can use optimistic locking. Optimistic locking makes  
sure that you can not save stale data to the DB. It doesn’t help with  
reading of stale data though.

Put the following ‘special’ column in your migrations for MyTable:

t.column :lock\_version, :integer, :default =\> 0

The version number is automagically incremented on every save by  
Rails. If your lock\_version is out of sync with that of the DB, i.e.  
someone else has updated your record while you had it in memory, then  
you get an exception.

As a final solution you could write attribute accessors for your  
model that force the object to reload itself every time you access  
the data. It is not a 100% guarantee of freshness (and it will floor  
your DB), but it works. For example:

class MyTable \< ActiveRecord::Base  
def name  
self.reload  
read\_attribute(:name)  
end  
end

Hey, you can even make it into a plugin so you can do:

class MyTable \< ActiveRecord::Base  
acts\_as\_nearly\_fresh :name, :title, :address  
end

(I’ll leave the plugin implementation to you; I find naming act\_as\_\*  
plugins more fun than writing them)

Hope this helps,

-christos
